Steps To Figuring Out Performance Issues

Programming performance issues can be a frustrating and time-consuming problem for developers. However, tracking down these issues is a crucial step in creating software. Here are some steps that developers can take to track down programming performance issues:

The first thing to do is ALWAYS hook up a profiler to your code, reproducing your issue, and measuring what is causing it. Performance issues are often not obvious and if you don’t profile you’ll waste a bunch of time speeding up things that don’t matter(or just hide the base issue).

In my experience, here are the main areas you get performance issues:

  • DB
  • DB
  • DB
  • DB
  • API Calls
  • External Access

A little hint: most of the time you are optimizing your code and not these other areas, you are reducing readability and not significantly impacting your load times for users.

Outside of these issues, it is often something silly a developer is doing. Some of the things I’ve seen:

  • Pulling the whole table down(all 1 million records) then filtering on the application server
  • Creating new instances of classes that do a lot of work on creation instead of reusing them
  • Really bad exception throwing that is used as control flow
  • Sending down 8 megabytes of HTML for a page, of which 6 megabytes is double escaping special characters (sending ////” instead of “)

Once you figure out where the main areas of slowness, it’s time to refactor!

Form Validation is No Fun

Over the years Software Engineering has gone through many iterations of best practices. Form field validation is no exception to this.

The morale of the story here is stop rolling your own validation. This is one of those things that seem super easy to do, so you just quick roll your own and then move on. Except you never move on because you’ll get tickets to fix stuff until the end of time.

Let’s talk about email validation as an example:

[email protected]
Early on, email was validated by checking if the email had letters, an @ sign, letters, and then ended with .com. This worked great until…

[email protected]
People started using subdomains for email. So we allowed for that. This worked great until…

[email protected]
People started using other TLD’s. Now we change validation to be the email had letters, an @ sign, letters, and then ended with .[com,net,org,gov,edu]. This worked great until…

[email protected]
People started using numbers in their emails. So we allowed numbers in the emails. This worked great until…

[email protected]
People started using special characters in their email (think periods, plus signs, etc). So we allowed for those. This worked great until…

[email protected]
All kinds of TLD’s became a thing. The wild west of TLD’s. So then we just said anything after the dot. This worked great until…

[email protected]
Some very nerdy people used IP addresses instead of domains. So we allowed IP addresses. This worked great until…

me@0:0:0:0:0:0:0:1
Some really nerdy people started using IPV6 instead of IPv4. So we allowed for that.

Don’t even get me started on validating if something is a valid IP address.

Incident Response

Incident response is a critical aspect of software engineering – the process of identifying, responding to, and resolving incidents that occur within a software system. In order to effectively respond to incidents, software engineers can use the Incident Command System (ICS), a structured approach to incident management that is commonly used in emergency response situations.

The ICS is a standardized approach to managing incidents that involves a hierarchical system of management and coordination. The system is designed to promote effective communication, coordination, and decision-making during incidents. The ICS is made up of five functional areas:

  1. Command: This is the overall direction and control of the incident. The command function is responsible for establishing priorities, making decisions, and delegating tasks.
  2. Operations: This function is responsible for carrying out the tactical objectives of the incident. This includes managing resources, implementing tactics, and ensuring safety.
  3. Planning: This function is responsible for developing and maintaining the incident action plan. This includes collecting and analyzing information, developing strategies, and identifying resources.
  4. Logistics: This function is responsible for providing the resources and support necessary to carry out the incident action plan. This includes managing supplies, facilities, and equipment.
  5. Finance/Administration: This function is responsible for managing the financial and administrative aspects of the incident. This includes budgeting, procurement, and documentation.

The ICS can be applied to incident response in software engineering by adapting the system to fit the unique needs of the software development process. This involves identifying the functional areas that are relevant to software engineering and adapting the ICS structure accordingly. For example:

  1. Command: This function would be responsible for overall management and decision-making related to incident response in software engineering. This would include establishing priorities, delegating tasks, and ensuring that the response is coordinated and effective.
  2. Operations: This function would be responsible for carrying out the technical objectives of the incident response. This would include managing resources, implementing tactics, and ensuring safety.
  3. Planning: This function would be responsible for developing and maintaining the incident response plan. This would include identifying the scope of the incident, analyzing data, and developing strategies for resolving the incident.
  4. Logistics: This function would be responsible for providing the resources and support necessary for incident response. This would include managing equipment, software, and other resources needed for resolving the incident.
  5. Finance/Administration: This function would be responsible for managing the financial and administrative aspects of incident response. This would include budgeting, procurement, and documentation.

Another concept to consider is corrective and preventive action (CAPA or simply corrective action). During an incident, corrective action is the most important thing. Often after an incident we forget preventative action – how are we going to prevent issues like this in the future? Especially think of related errors – often for an error to become an incident, there needs to be failures at multiple levels. The initial corrective action is often to fix one of these multiple failures – but if you don’t go back and fix the other failures you’ll have a boobytrap for a future developer to step on and have the issue again.

YAGNI – You Ain’t Gonna Need It

YAGNI and Agile

One of the hardest things to do in software development is to respect “you ain’t gonna need it” and “keep it simple stupid”. Every time I go to implement a feature, I can think of 50 extra things I should do to make it ‘complete’ and exactly what I want. It is so helpful to hit things with an Agile and iterative frame of reference. Build an MVP(minimum viable product) and publish! Extra features can come later as they are actually needed.
Recently I was working on a login page. Very simple and shouldn’t take long, right? So first I implemented the bare minimum, users with hashed passwords and a simple ‘login failed’ or setting up session and pushing to the home screen.
Then the things it should also have went through my mind.

  • Login pass/fail Tracking
  • Password resets
  • User unlockouts
  • Login with your email
  • Brute force alerting
  • Remember me
  • CAPTCHA
  • Security questions
  • Pretty HTML emails for various alerts
  • A Linux-like password storage format to allow for forwards/backwards compatibility and different algorithms
  • Verify timing doesn’t change for the various failure reasons(so a bad actor can’t figure out if a user exists by how long the failed password request takes)
  • Audit cookie security
  • Login with Facebook etc.
  • Two factor authentication

I could now spend a week setting all this up instead of building features that really bring the product forward. These are all great features, FOR LATER!

The Agile approach – small bite sized increments is great here. I wouldn’t want to give all the features to QA or the customer at the same time. It’s too much. First deliver your MVP and iterate from there. You’ll probably find out no one would have used half of the nice-to-haves that you thought would be good to have, so you can spend your time on the important stuff!

NLog Setup

Every time I make a file new project I need to add logging – how many times have I spent time figuring out what needs to go where, how to format the error email, and how to log uncaught errors(oh noes!). Too many times. So here is me condensing adding NLog to a web project quickly and easily:

Install NLog.config(and with it NLog) on your web project.

Add these to NLog.config:

<targets>
 <target name="Mail" xsi:type="Mail" html="true" subject="Error Received" layout="${longdate} LEVEL=${uppercase:${level}}, LOCATION=${callsite:className=true:includeSourcePath=true:methodName=true}, MESSAGE=${message}${newline} EXCEPTION=${exception:format=tostring,StackTrace}${newline" addNewLines="true" replaceNewlineWithBrTagInHtml="true" to="[email protected]" from="[email protected]" useSystemNetMailSettings="true" >
 </targets>
<rules>
 <logger name="*" level="Error" writeTo="Mail" >
 <logger name="*" level="Fatal" writeTo="Mail" >
 </rules>

Add this to global.asax.cs

protected void Application_Error()
 {
 Exception lastException = Server.GetLastError();
 Logger logger = LogManager.GetCurrentClassLogger();
 logger.Fatal(lastException);
 }

There is some feature interaction with how you handle your errors, to get things working you may need to temporarily change customErrors mode to Off in web.config(but this should never go to production!)

Confidentiality, Integrity, Availability

The CIA triad of Confidentiality, Integrity, Availability refers to three necessary security components of software, at a bare baseline.

Confidentiality
Software(and its’ developers) are often exposed to sensitive details. These details should only reach the people the client expects. Users must be able to understand what data can be seen by who.

Integrity
Data should only be changed purposefully by users. Data, along with corresponding metadata, should be stored safely, securely, and with solid backups.

Availability
Access to your service and the data is paramount for users. Redundancy, fail over, backups, disaster recovery, and rigorously maintained infrastructure are all important parts of continuing availability.

 

So why is this important? Every software developer needs to have have strong knowledge of security – writing software without that knowledge is irresponsible because the consequences to software providers and users. Any tiny bit of leaked data, email address, user name, can be used as a ‘wedge’ in getting more data.

OWASP is the best source for information related to your specific technology stack and implementation. Please go through and read each of their recommendations for every application you write.

This is important because the deck is stacked against you: you have to defend from every possible attack, attackers only have to find one weakness.

Exceptions Deserve to be Handled

Some code smell I came upon today! Exceptions should always be handled in some way, even if just logging it and continuing on(the next person troubleshooting a problem will thank you). Also, exceptions should be exceptional – they are slow and break up code flow; avoid using them for normal circumstances, like bad user input.


try
{
   //do something
}
catch (Exception e) { }

Development, Testing, and Quality Assurance

How important is it that your software runs correctly and to spec? For most software it is of the utmost importance. One of the Joel Test 12 is “Do you fix bugs before writing new code?”. Smart development, testing, and QA help prevent bugs in software.

Fixing Code Before Production and After

Fixing code before it goes to production will save you time. I have had bugs that would have taken 30 seconds to fix before going to production that I spent more than a week on fixing after it went to production because it messed up data in another system.

Ways to Prevent Bugs

One of the big things in the programming industry in recent years has been unit testing(and integration testing, TDD, BDD, etc.). Testing is good! It helps find bugs before they are a problem and helps developers make changes in important parts of the code base and have more confidence that they aren’t causing problems in other parts.

If I had a dollar for every time I was asked if I’m writing unit tests why QA is needed, I would definitely have a few dollars. Very simply, QA finds bugs that unit testing does not. Unit and integration testing catch many things, but even though I keep making better software, users will always find a better way to break software.

Featuritis(Scope Creep)

Scheduling software is hard. Estimating software is hard. Deadlines in software are hard.

When someone says “we need this thing you estimated for 4 weeks in 2” the question is “what can we cut or push back into another release?”

Not managing the scope creep situation well ends up with:

  1. Increased Costs: Scope creep can lead to increased costs, as additional resources and time are required to meet the new requirements. This can impact the project’s budget and profitability.
  2. Delayed Timelines: Scope creep can also lead to delayed timelines, as additional work is added to the project. This can cause frustration for stakeholders and can have a negative impact on the project’s overall success.
  3. Reduced Quality: Scope creep can also lead to reduced quality, as developers may be forced to rush to meet the new requirements. This can result in code that is less efficient, less secure, and more prone to bugs and errors.
  4. Disruptive to Team Dynamics: Scope creep can be disruptive to team dynamics, as team members may become frustrated with changes and additional work. This can impact team morale, productivity, and collaboration.

Here are some ways to avoid scope creep in software engineering:

  1. Clearly Define Project Scope: Clearly defining the project scope at the outset can help to avoid scope creep. This includes identifying key objectives, deliverables, and timelines, and outlining a plan for how they will be achieved.
  2. Communicate Effectively: Effective communication between stakeholders, team members, and project managers is essential for avoiding scope creep. This includes keeping stakeholders informed of any changes or updates to the project and maintaining open lines of communication between team members.
  3. Manage Expectations: Managing stakeholder expectations is critical for avoiding scope creep. This includes setting realistic goals and timelines, and being transparent about any potential challenges or roadblocks.
  4. Document Changes: Documenting any changes to the project scope can help to avoid scope creep. This includes maintaining a detailed project plan and updating it regularly as changes occur.

You’ll notice that managing expectations and communicate effectively are basically the same thing – that’s on purpose. Communication is the most important part of the software engineering process.

When Building An Interface, Think About the Customer

When building an interface/class, a software engineer should think about how other software engineers are his target customer. This means that the interface should be designed with the needs and preferences of other software engineers in mind.

Here are some reasons why software engineers should consider other software engineers as their target customer when building an interface:

  1. Efficiency in Workflow: Other software engineers will have similar workflows to the developer who is building the interface. The interface should be designed to facilitate efficient workflows, using well-established patterns and conventions to streamline the process.
  2. Customization and Flexibility: Other software engineers may require customization or flexibility in the interface to cater to their individual needs. The interface should be designed to allow for customization and flexibility, using modular components and flexible layouts.
  3. Clarity and Consistency: Other software engineers may be working on different parts of the project or may be working on the same codebase at a different time. The interface should be designed to ensure clarity and consistency, using clear labeling and navigation, and consistent design patterns.
  4. Consideration for Technical Competence: Other software engineers may have different levels of technical competence, and the interface should be designed to cater to this variance. This can be achieved by using clear error messages, detailed documentation, and helpful tooltips.

In conclusion, when building an interface, software engineers should think about other software engineers as their target customer. By designing interfaces that cater to the needs and preferences of other software engineers, developers can create interfaces that are efficient, flexible, clear, consistent, and considerate of technical competence. This can help to ensure that the interface is well-received and widely used by other software engineers, leading to more effective and efficient software development.