Avoiding another boolean check

A developer wrote some code like this:

	public void RunScheduledJob()
	{
		if (_loggingEnabled)
			Log.Write("Main Job Complete", _category, _severity, _customData);
	}

	public void LogWrite(string message)
	{
		if (_loggingEnabled)
			Log.Write(message, _category, _severity, _customData);
	}

I’ve removed some extra code to make the example clearer, but the RunScheduledJob would do something then write to a log if the feature is enabled. The LogWriteMethod writes to a log if the feature is enabled.

Although it’s not a major improvement, the obvious thing to do would be to use the LogWrite method in the RunScheduledJob method like this:

	public void RunScheduledJob()
	{
		LogWrite("Main Job Complete");
	}

	public void LogWrite(string message)
	{
		if (_loggingEnabled)
			Log.Write(message, _category, _severity, _customData);
	}

So the reviewing developer Jim, pointed this out to Rich:

Jim: Could you call the LogWrite method here?
Rich: I could do but it would then evaluate _loggingEnabled twice for no reason.

Now, Jim and I were baffled what he meant. Even if it did have to check _loggingEnabled, it is a simple boolean so would only waste 1 millisecond to evaluate again. There’s no question of performance here; only clarity.

Rich then suggested this code as an improvement:

	public void RunScheduledJob()
	{
		if (_loggingEnabled)
			LogWriteNoCheck("Main Job Complete");
	}

	public void LogWrite(string message)
	{
		if (_loggingEnabled)
			LogWriteNoCheck(message);
	}

	private void LogWriteNoCheck(string message)
	{
		Log.Write(message, _category, _severity, _customData);
	}

So we have lost a bit of clarity.

It’s weird how sometimes developers have moments of madness and over-complicate simple things. This particular developer has 30 years programming experience!

Hidden Scanning Portal

Many years ago, my colleague Andy came up with a great software hack to fix a bug. I didn’t understand the fix at the time, so don’t remember the details, but the bug manifested as a red box replacing a UI control whilst the user was scanning a paper document.

Andy implemented a solution dubbed the “Hidden Scanning Portal,” a dialog box that remained invisible until the scan was complete, after which it was disposed of.

After a few months, another developer, Joe, convinced they had discovered a more permanent solution; removed Andy’s Hidden Scanning Portal. This action inadvertently introduced a new bug, so the Hidden Scanning Portal was swiftly restored, averting further complications.

Our Team Lead, Matt revealed that failing to fix the original issue could have resulted in a fine of £16,000. This revelation cast Andy’s quick fix in a new light, attributing a significant value to what might have otherwise been seen as a mere temporary solution. 

Andy’s reaction to the situation was a mix of pride and frustration. Despite his contribution to saving the company from a hefty fine, he lamented the lack of recognition in the form of a modest pay rise.

“and they didn’t even give me a measly 3% pay rise”

Andy

Quick fixes might not be ideal, and increase “technical debt”, but they can provide immediate relief, avoid hefty fines, and great stories to reminisce about.

Crazy Code Design

Here is a selection of poor code design that I have come across over the years.

Opacity Slider

Sometimes, programmers write simple programs to help them, or their team. When I first joined this company, they were using a more basic version of a source control like SVN, and someone had designed a program to help with Code Reviews. On the tool, they had a slider that changes the opacity of the dialog, so you can make it see-through. It seemed like a case of the developer simply doing it because they could, and not because anyone actually found the feature useful. I suppose you could be more creative if it’s only used internally, and not for a customer; but still incredibly pointless.

Law of Demeter

Law of Demeter, also known as the principle of least knowledge, advocates for a design where objects are loosely coupled and only communicate with their immediate acquaintances. This means that a method in a class should only call methods on:

  • Its direct components.
  • The object itself.
  • Objects passed as parameters.
  • Any objects it creates.

In practice, this means you shouldn’t have a massive chain of methods/properties.

One example of breaking this law that I saw in our code looked like this:

responseMessage.acknowledgements.conveyingTransmission.controlActEvent.reason[0].detectedEvent.code.code

Awful.

Partial Record

One of our modules can potentially show a large amount of data. The data can come from the local record, or if there is a sharing agreement, it can come from other companies that they share with. There are certain screens where you don’t need all the information, so to try and cut down loading times, we have this concept of a Partial record and a Full Record.

	public IRecordPartial Partial
	{
		get
		{
			return IsFullLoaded ? Local : EnsurePartial();
		}
	}

The logic, and wording gets confusing real fast. The property above is called Partial, but there is a check for IsFullLoaded which implies that Local can be Full, and not just Partial like the property says. When you look further into the code, Local might not even be local because it can contain shared. Mindbending.

PercentNull

Coming up with descriptive names is always a challenge in programming, and there is occasions where naming can be ambiguous. However, I have no idea what a method called PercentNull does here:

transactionOut.Surname = helperFacade.PercentNull(customerDetail.Surname);

If it assigning the result to Surname, then it should be returning text. Nothing immediately obvious comes to mind if you are passing in Surname to a method called PercentNull and getting a Surname from that. So it’s not like it is returning a percent number if it can, or Null if it cannot. Or returning the percentage that the text contains whitespace. 🤷

How High

	public enum SeverityScale
	{
		None = 0,
		Low = 1,
		Medium = 2,
		High = 3,
		ExtraHigh = 5,
		VeryHigh = 6
	}

We have this enum to represent the Severity. It makes sense until you get further than High. Extra High makes sense to be more severe than High, but should Very High be higher than Extra High? Extra and Very sound like synonyms. You need something more extreme like Extremely High to make it immediately obvious what the ranking is.

Focussed or not?

	public void SetSearchBox()
	{
		SearchFocused = false;
		SearchFocused = true;
	}

When you see code like the above, it is most likely that the code is doing something weird, and because no one worked out how to fix the original issue, you then end up writing more weird code to work around that. These “hacks” just stack up and are hard to remove. If you try to do the right/honourable thing and remove a hack, then you will probably see some strange behaviour which then means you remove more code, and maybe more code when you find more problems. Repeat until you are left with the original issue which you then have to fix.

So how can setting a property to false, then immediately setting it to true actually do something? Probably if the property has loads of logic and side-effects. Probably best not to look. 🙈

Random Parameter

		public Organisation(bool randomParamToChangeSignatureForFasterConstruction)
		{
			// Had to create a new constructor that doesn't initialise internal state, param isn't used.
		}

The thing that is scary about this strange code, is that it was written by one of our smartest developers. I have no idea why he had to create an extra constructor. Presumably the parameter is there because the “default” constructor already existed. Intentionally not initialising data sounds like a recipe for bugs though. Maybe it needs a redesign.

Slow Request

I remember my Dad telling me a story of a software team putting a delay into their code. Then each month, they would simply reduce the delay a bit and tell their managers they have been working hard on performance improvements.

if (Helper.SlowRequest)
	Thread.Sleep(15000);

I found the above code in our codebase but it relies on a configuration value being present in the config file. It was present and set to true by default for Developers though so would always be slow. Changing the value to false would speed it up, but you have to know that it exists to change it.

<add key="SlowRequest" value="true"/>

Although it doesn’t affect our customers, there’s always the chance something will go wrong one day and it could affect them.

Boolean “Mode”

If you want to handle many options, you often use an “enum”. Using a “Boolean” which represents 2 values (true/false) is a very weird choice…

 <param name="mode">If set to <c>true</c> then [mode] is a delete operation, else add, edit and none operations</param>

so

true = delete

false = add OR edit OR none.

If you put the wrong value, then there’s an if statement after. So if you say it’s a delete and it isn’t, then things don’t get deleted.

		if(!mode)
		{
			if (@event.updateMode != vocUpdateMode.delete)
			{
			}
			else
			{
				if (@event.updateMode == vocUpdateMode.delete)

Not Supported Property

	public virtual String UploadedBy
	{
		get { return _document.Observation.EnteredByUser.DisplayName; }
		set { throw new NotSupportedException("Setting UploadedBy is not supported"); }
	}

Isn’t that Set a complete dick-move. If you call it, it will crash. If the setter wasn’t there at all, you would know it shouldn’t be set.

I guess it could be designed with the expectation that you would override the property. However, I thought it wouldn’t be set correctly, because the “get” returns a massive chain of properties. So it’s not just the case of setting a variable, it’s actually document.Observation.EnteredByUser.DisplayName that needs to be set, and that is breaking the Law of Demeter anyway.

Mutual Exclusive

This is gonna end in tears

private Boolean _isSingleClick;
private Boolean _isDoubleClicked;

Not only are there better ways than detecting clicks, when you have multiple variables tracking similar concepts like this, you can easily end up in invalid states. If _isDoubleClicked is true, then you would expect _isSingleClick to always be false. But it is easy to make a mistake in the code and not set it which then leads to a bug.

Notifications

		public bool IsNotificationConfigEmailEnabled()
		{
			if (!_configSmsEnabled.HasValue)
				_configSmsEnabled = NotificationConfiguration.IsEmailEnabled;

			return _configSmsEnabled.Value;
		}

The fact that this code had been there years means it should work. But when the property is supposed to be checking if Email is enabled but the code only looks at SMS enabled; then who knows how it works.

Resizing

int parentSize = Parent != null
                ? Parent.Width
                : Screen.PrimaryScreen.Bounds.Width;
 
var availableSpace = parentSize - _clientLocation.Y - _yOffset;

What a nonsense calculation that is! We want to calculate the height of a pop up box and make sure it can fit within the window. So we look at the width of control, or maybe the width of the monitor that they might not be using (if they actually have the program on their secondary monitor), then minus the Y coordinate of the window which would be related to height, and not width.

Splitting

Sometimes programmers like jamming as much code as they can on what is technically a single line. It is an absolute nightmare to debug chained logic like this:

return
	RequiresSingleItemOrder(item, customerRequestsSplit)
	?
	null
	:
	batchOrders
	.FirstOrDefault(
		orderInstance =>
			(orderInstance.IssueMethod != IssueMethod.Electronic || orderInstance.Items.Count() < 4)
			&&
			!orderInstance.Items.Any(m => RequiresSingleItemOrder(m, customerRequestsSplit))
			&&
			orderInstance.IssueMethod == issueMethod
			&&
			orderInstance.OrderType == OrderType
			&&
			orderInstance.IsUrgent == isUrgent
			&&
			(!ShouldSeparateControlledItems
			||
			orderInstance.AnyControlledItems == item.IsControlledItem)
			&&
			orderInstance.Warehouse == Warehouse
			&&
			!Authorisation.Separator.ShouldBeSeparated(authoriser: authoriser, orderAuthoriser: orderInstance.Authoriser)
			&&
			(!ShouldSeparatePrivateItems
			||
			orderInstance.IsPrivate == isPrivate)
			&&
			MatchesForRepeatOrdering(item, orderInstance)
			&&
			NullAndNonsequentialEqual(separationTypeIds, orderInstance.SeparationTypeIds));

Funny Youtube Comment

I saw this comment on a programming video on YouTube. It is remarking on how you can write really confusing code as a way to increase your job security because you can be in charge of code that only you can read:

And remember, kids – if you nest multiple null coalescing operators into a single line of poly-nested ternary operators, that’s called “job security” – cause ain’t no one wanna maintain that code when you’re gone.

return a> b ? a < c ? a != d ? e ?? f ?? 0 : f ?? g ?? : 0 e ?? g ?? 0;

Typescript Example

Years ago, we started rewriting our C# program using Web Technologies. Since everyone was new to Javascript and Typescript, everyone wrote awful code. But then you didn’t know if it was good or bad. One of the first bits of code I saw when I joined their team was this:

export const Actions: { [key: string]: <T extends {}> (value: T) => IAction<T> } = {
 setModuleName: <T extends {}>(value: T): IAction<T> => CreateAction<T>(ActionTypes.setModuleName, value),
};

Don’t ask me what it says, because I have no idea.

Contradiction

InsertUpdateResourceImmutableProperties

It’s so frustrating to read, it makes you want to punch someone. Immutability means it shouldn’t change after it has been created. So how can you Update something Immutable? Luckily it has a comment explaining it:

   -- If we are about to insert the most upto date version of the resource, then we should update the
    -- resources immutable properties, because they might have changed in the source system. (Even though they shouldn't).

Well, I am still none-the-wiser.

Boolean Extensions

If you have a boolean variable and you want to check it is false, you can just write:

			bool example = false;

			if (example == false)
			{
			}

Now with this handy extension method:

public static class BooleanExtensions
{
	public static bool IsFalse(this bool boolValue)
	{
		return !boolValue;
	}
}

You can now write:

bool example = false;

if (example.IsFalse())
{
}

What’s the point in that? No advantage really is there?

Not Set Up

		get
		{
			if (_setup)
			{
				_setup = false;
				return true;
			}

			return _noDocumentsInError;
		}

In the get property, we check the value of _setup. If true then we set it to false, and the overall result returns true. However, if we immediately call the same property, it will just return the value of _noDocumentsInError instead. It’s bad design to have side-effects in a get. Gets are supposed to return a value, and not set things. Then we seem to have different fields tracking different concepts which just looks like it will be prone to errors.

Reload

	public void ReloadTriggers()
		{
			// To be implemented
			return;
		}

This code doesn’t even need a return statement. It is just there for the bantz. When this code is in a module that is very error prone, and you have a method that is not implemented and does nothing at all, then doesn’t give a good impression does it?

Dialog Events

            _msgBox.ShowDialog();
        	return _continueWithSelection ? DialogResult.OK : DialogResult.Cancel;
}
 
private void Cancel_Selection(object sender, EventArgs e)
{
       _continueWithSelection = false;
       _msgBox.Dispose();
}

You can get the dialog result when the dialog is closing. However, this developer has decided to create their own event handlers for the button clicks, then using the variable to decide if it is a DialogResult.OK or Cancel.

NoEncryptionEncryptor

new NoEncryptionEncryptor() 

Is this an Encryptor or not?🤔

SillyException

You throw an Exception when something bad has happened. However, in our code there is a concept of SillyException where you are supposed to ignore it because apparently, it isn’t a real error. It’s only used in a specific part of our codebase though so goes undiscovered for ages. A colleague Michael found it again and we were reminiscing on a bug I found.

Michael 11:33: 
if (mapped is SillyException) return 0;         // Avoid throwing the SillyException

Me 11:33:
I love sillyexception

Michael 11:33:
/// <summary>Represents a data provider exception that doesn't indicate an actual error,
/// and should be ignored.</summary>
[Serializable]
public class SillyException

Me 11:34:
I remember David going on about SillyExceptions and it took me ages to realise he was referring to an actual thing

Michael 11:35:
"I keep getting this SillyException"
what kind of exception is it David?
IT'S A SILLYEXCEPTION
YES, BUT WAT KIND

Me 11:35:
yeah, it did go something like that

Michael 11:35:
haha

Me 11:37:
I think it was around the time he spent weeks investigating that bug I found that no one else could recreate
and I thought he had worked it out when he said he was getting a SillyException

 lame async call

var result = client.BeginUploadFile((Stream)payload, endpoint);
bool uploadCompleted = false;
while (!uploadCompleted)
{
	uploadCompleted = true;
	if (!result.IsCompleted)
	{
		uploadCompleted = false;
	}
}
if (!uploadCompleted)
{
	throw new Exception($"Failure occurred while uploading the data");
}
client.EndUploadFile(result);

weird that they set it to true, then set it back to false. Then it will never get to the exception, it will just be an infinite loop because the check is outside the loop that will only exit if it is complete.

Is this just a reimplementation of a lame async call?

New Laptop

I was quite excited to receive my new work laptop given that my current laptop is old, has a low resolution display, and has been running really slow recently (mainly due to the increasing amount of “security software” mandated by IT).

After being told I was in the next group to receive mine, I was asked if I would be in to be able to take the delivery. So I responded that I would be in all week since I was working Mon-Fri

I received an email mid-Friday saying it had been dispatched next day delivery, but I planned to be out Saturday. Despite staying in to receive it, it never arrived. On Monday, I checked the tracking number and had a status update of “Partially Dispatched” then “Complete“; whatever that means. On a different page, it said it was “Out For Delivery”, but showed the expected delivery date as “tomorrow”. Soon there was a knock on the door, and there it was. So the status pages weren’t helpful at all.

So I turned it on and tried to add my account to it. However I saw a message saying the feature wasn’t supported.

A member of IT contacted me and said I should receive my laptop today. A bit late. He was on call to help me set it up which was nice. I asked if there was anything special to do because it wouldn’t let me log in. He sends me a PDF of instructions. Why wasn’t this sent to me before the laptop arrived? Why did I have to request it after attempting to set it up myself?

Regardless, I had selected the correct options so told him the step it was failing on. He suggested maybe I didn’t have an internet connection. So I enabled aeroplane mode and got an error about not having a connection, so it wasn’t that.

I messaged someone that I knew had the same new laptop. He said a team member had just received theirs too and it was supposed to have some kind of initial setup on it where it would have a Device Name. The first thing it asks when I turn it on is to set a device name so it hasn’t been set up. It was also supposed to have an Asset Sticker on it, but mine was a brand new, sealed laptop with no sticker on it.

It sounds like that IT put an order in via a third-party who are supposed to order the laptops. configure them, put a sticker on them, then ship them out. So they had 1 job, and didn’t do it.

So I told IT and they said they could configure something on their end which they did. As usual though, despite their process installing some default apps like Office, nothing else was configured so I had to install SQL Server and Visual Studio, and configure loads of options to set everything up. It’s such a time-consuming and error-prone process. Why can’t we just have a standard “Image” that gives us the majority of what we need?

A few days later, my Asset Number sticker arrived in the post. A large padded envelope inside another larger padded envelope. For 2 stickers. There was also 2 A4 paper which was the invoice; it didn’t need to go to 2 pages but it was badly formatted. Then they put in a couple of adverts for their services. What an absolute waste.

Recently, we promote “green” ideas, talking about reducing carbon emissions and being energy efficient etc. We also seem to want to reduce costs where possible. Then they do stuff like this. Even though it’s a third party that has caused the problem, it is still part of their business process isn’t it?

Bulk Approvals Feedback

In our software, we have a task list where “requests” go. They can be created by our users, or online by their customers. We have 2 boxes where these go: “Requests” and “Requests With Queries“. As far as I understand, the Requests are often safe to approve because it’s basically just a repeat order and added by the staff member so has already had one official approval on it. When there is some uncertainty, they go into the “With Queries” box for more scrutinisation. The requests coming from online always go into “With Queries” and require more scrutinisation.

The time it took to click approve and then load up the next task was quite slow. We added a Bulk Approval feature where the user can view tasks quickly, then approve several at once which means they don’t have to go through the load/send/load/send/load/send workflow. It’s more like load/load/load; and the sending can be done in a background process.

For Requests, this bulk feature worked fine because they can be quickly reviewed, then sent. For ‘With Queries’, it made sense that our users would want to bulk review the user-created ones, but the customer-created ones would require further time to review. So we decided to create a new box where the customer-created ones go.

This was requested by some of our users, and it made sense to us. However, we didn’t ask all our users if it was appropriate for them.

So when it went out, many users complained that we had “doubled their work“.

The comments from our users often seemed strange, but many seemed to be saying they had a Receptionist that went through all the tasks and reassigned the task owner to different staff members so they all had an even amount of tasks. Then each user would check their tasks and approve them. They referred to this as “regulated distribution”. We were baffled why having the same number of tasks as before but just located in 2 boxes rather than one would be a problem.

One user said this:

“unfortunately we don’t work like that. The requests have to be counted – so many queries and so many straightforward. They are allocated daily and completed but have to be collected and centralised first.. Nightmare for us.”

Another user said this:

We cannot work out now within this new box which are queries and which are not so we are having to open every single one ( 500 today) in order to sort them out.

But before, all these tasks would appear in the Requests With Queries box because they were all customer-created. Now in the Requests With Queries box, they should be able to review these faster because each one would require the same level of scrutiny, whereas before, they would have to keep looking at the “source” to see if it was from a user or customer to decide what level of checking it required.

I think it must be the case of just being shocked when something changes and reluctant to adapt.

During development, we also debated what the Review Date really meant. If it was set, then we check if the date has passed and don’t allow these to be bulk approved. However, customers can have no Review Date at all which we interpreted to mean it wasn’t applicable to them, so we allowed all their tasks to be bulk approved. However, one particular organisation thought this was very unsafe for them. They wrote an interesting write-up, full of capitalised letters and very much geared to a Hazard Matrix:

This issue has been discussed at the Joint IT Committee, who are expecting feedback in due course. 

The Committee's concern is that there is a HAZARD that items may be issued through Bulk Approvals that have not been appropriately reviewed. The CAUSE of concern is that the Bulk Approvals module includes orders for customers who have no items Review date. Where an organisation's business operations involve using items Review date to govern their ordering, the EFFECT may be that a customer whose items has not been appropriately reviewed may have bulk approved orders (potentially repeatedly). The HARM to the customer may be any of the wide range of harms that can come about through unreviewed access to order items including death. Therefore a LIKELIHOOD needs to be calculated (you are best placed to do so as you can audit your records to identify how many customers have had repeat orders issued through Bulk Approvals, describe any case reports you have had of customers who have been harmed (and near-misses), and estimate the future risk by identifying how many customers have repeatable orders and no review date.

I believe that on your hazard matrix, the CONSEQUENCES therefore could plausibly result in death = CATASTROPHIC

The LIKELIHOOD I would appreciate your guidance on, but I wonder if it might be UNLIKELY i.e. likely to occur some time (the longer it is running the higher the chance), or if you have other CONTROLs I'm not aware of, possibly EXCEPTIONAL i.e. unlikely, but may occur exceptionally, which would give the HAZARD a rating of HIGH or MEDIUM.

The Committee would therefore be grateful for more detailed feedback on the HAZARD so that we can respond to our Members. This might be the relevant row from your Hazard Log for example, but a narrative description would be fine.

The suggested REACTIVE CONTROL is to consider excluding those customers from Bulk Approvals which would ELIMINATE this cause. There are alternative controls but none that would eliminate the cause entirely that we are aware of. In any interim, a organisation could mitigate this risk until any change in module behaviour if they audited their customer records to identify customers who have current active repeat orders but no review date.

Skin-tone plasters

Big changes coming from the Employee Forum. We are getting a variety of skin-tone plasters (band-aid) for the first aid kit. What sort of insane social justice warrior asked for that?

If anything, the default plaster is brown so us white folk need lighter ones.

This is the most extreme woke thing I have ever heard of. I don’t think we will beat it.

Skin Tone Plasters.  A great shout and a big thank you for the lack of variety being highlighted to the Employee Forum.  Aligning to our environmental credentials, the incumbent plasters will remain where they’re within a 3yr use-by lifespan.  As we move to replace, this will be done with a wide variety of skin colour matching plasters. 

I asked a friend what he thought of this:

Jack: I've heard of this before, so dumb

Me: Bet we get sacked for using the black plaster

Jack: Haha I would, just to make a point. Whoever came up with this has too much time on their hands, and whoever gets upset about wearing a wrong coloured plaster is a melt

Me: I should swap 'em with kids ones with cartoon characters on them

I do raise a good point there. If you did use the wrong colour plaster, would people get offended? What happens if you took the last dark-skinned one and someone saw you and they wanted it?

How often do you need a plaster when you are in the office? If the plaster is in a visible part of your body, is the presence of the plaster uncomfortable/embarrassing anyway regardless of colour? I think the default brown one is probably a good compromise for all skin types anyway, but I suppose modern ones can be white or transparent. 

This surely has to be a case of a white person suggesting this, using their wokeness to raise an injustice against darker skinned people, even though no dark-skinned person was actually offended. However, if you now take the plaster that is reserved for them; then they will be offended.

Do we have the same policy in regards to bandages? They are usually white too.

Incompetent Developer Tales

We had an Indian Developer who wasn’t very good and he wasn’t that great at communicating in English. I don’t mind people starting out as a Junior and improving over time, but sometimes I think you need to have a mindset for quality and care about your work, and Manikandan didn’t seem to have that.

Text

Making a change which involves updating text is one of the easiest changes in software development. This particular area of the code had unit tests to check the message we were displaying to the user. So if the requirement changed, you would have to update the unit tests, then change the actual logic. Manikandan changes the code, but for some reason puts an extra space at the end, and doesn’t update the unit tests.

“As suggested the changes were made and PR got patched.” 

Manikandan

Another change he did involved changing the file path of where a specific file (sqlite) was meant to be. He ends up changing the file path for some other file instead. I pointed it out and he claimed he had tested it.

“I have dev tested this yesterday, it looks like i have missed sqlite folder path.

Mistakenly i have taken up the cache folder.

Will update and patch the PR. Apologies as i have misplaced the path location mistakenly and have corrected it now and done dev testing”

Manikandan

Corrupt Files

When viewing files that have been attached by users, some of these we natively support like text and images, whereas specialist files we allow opening externally. Some we blocked completely. 

A new change would allow files to be saved regardless if they were unsupported or we suspected them to be corrupt. We will inform the user of this though, so this was the 2 requirements:

When you attach:

This file “xxxxx.tif” has been successfully attached. However the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.

When you select “open file”:

This file “xxx.tif” cannot be opened because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.”

He writes the following note in the bug report:

Made a proper message information need to be displayed to the user as well as restricted further attachment of the corrupted file into user record history.

Manikandan

So that sounds like he is blocking suspected corrupted files, which is not the requirement.  When I looked at his code changes, it seemed like he had done the wrong thing.

So I ask him:

“Have the requirements changed since the product owner’s comment? It looks like you have the message that should be displayed, and it sounds like the attachment should still be saved.”

Me

he replies

“Corrupted Document will not be attached to the record. Once again checked in the database to confirm”.

Manikandan

So I reply again:

“Who has decided that it shouldn’t be attached to the record? The Product Owner said it should be attached and there should be a specific message shown to the user.”

Me

“Apologies for that, will check once again with product owner”

Manikandan

Got the update and have made the changes as per Document gets attached to the record irrespective of the document was corrupt or not. Will show a message to the user regarding the file corruption but allows the user to attach the doc irrespective of its correctness

Manikandan

So it seems he finally understands the requirement. However, when he submitted his change to review, it will show a message on Loading (but not the one the Product Owner asked for), but will still crash on Save so he hadn’t really changed anything.

Finishing my work

I had made loads of changes for a new set of validation, but didn’t have time to finish it off as I got moved onto a different project. I had to hand over my work to him. He made some changes and submitted it to me for review. One file I had already wrote the code to show the new message, but then he had added another IF statement, and added the exact same message, however it had some extra spaces in it! So redundant code, and it was wrong.

Another requirement was 

This Warning should be available irrespective of Admin Org flag...”. Yet he had an If statement to check for the flag.

else if(IsAdminOrg)
 {

There should be no IF statement because it should happen regardless if the flag is on or off.

In another code block, his logic was based on a check :

specialisedCode.Equals(SpecialisedCode.HDS3)

This equals check wouldn’t actually ever equate to “true” because the comparison was against different object types. And even if it did work, won’t this display the same text twice? He already added code to add it to the list, then had some code to add it again if the If statement was true:

 if (matchedItems != null)
{
	var displayName = matchedItems.GetAttribute("displayName");
	var specialisedCode = matchedItems.GetAttribute("code"); ;
	if (!allComponentNames.Contains(displayName))
	{
		allComponentNames.Add(displayName);

		if (specialisedCode.Equals(SpecialisedCode.HDS3) || specialisedCode.Equals(SpecialisedCode.HDS4))
		{
			allComponentNames.Add(displayName);
		}
	}
}

In another part of the code, he had this code

var hasExceptionalComponents = HasExceptionalComponents(sectionDefinition);

if(!data.IsSystemLibraryItem || (data.IsSystemLibraryItem && hasExceptionalComponents))

So if the first part of the if statement wasn’t true (“!data.IsSystemLibraryItem”), then it would evaluate the second part, but data.IsSystemLibraryItem would always be true (since it is just the inverse, and the opposite of “false” is “true”). So that bit could be excluded; so yet more redundant code from Manikandan. This would mean you could write:

if(!data.IsSystemLibraryItem || hasExceptionalComponents)

but what was he doing if this statement was true or false? Here is more of the code:

if (!data.IsSystemLibraryItem || hasExceptionalComponents)
	FormListFromTemplateSectionDefinition(sectionDefinition, allComponentNames);
else
	FormListFromTemplateSectionDefinition(sectionDefinition, allComponentNames);

That’s right, he was doing the exact same thing, so that code block can actually be one line:

FormListFromTemplateSectionDefinition(sectionDefinition, allComponentNames);

So the majority of the code he writes is just redundant. How can you be so incompetent?

When I flagged it to Manikandan, he said

or i am i missing it somewhere, sorry. lil bit confused on this, as i am alone working on this project.

Manikandan

This isn’t a misunderstanding of the requirements, it’s just a lack of care and thought.

Email Regex

When it comes to data entry, you can perform validation using Regular Expressions which defines a pattern/structure. Certain identifiers have rules, for example; an English postcode (I think) is 2 letters, 1 or 2 numbers, usually formatted with a space, then a number, followed by 2 letters. eg  HX1 1QG.

Software developers often come up with convoluted rules to try and define what an email address looks like, but I think they are inconsistent even between email providers that certain special characters can be excluded.

In our software, a developer had decided to change the regular expression in our email address validation. It was complex before, and it looked more complex after the new developer’s changes.

This was what it was:

return (Regex.IsMatch(emailAddress, @"^[A-Za-z0-9_\.\-&\+~]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$"));

And he changed it to this:

return (Regex.IsMatch(emailAddress, @"^([\w-]+(?:\.[\w-]+)*(?:\'[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$"));

Now, glancing at that, I have no idea what the advantage is. Some developers just assumed it was a good change and approved the change. What I noticed is that the end part was changed from [a-zA-Z] to [a-z], which means the last part of the email eg “.com” can only be written in lowercase, but previously we accepted “.COM“. As far as I am aware, email addresses don’t care about casing, so although it would be nice if users only entered them in lowercase, it seems an unnecessary restriction. Was it intentional? What else in this validation is different?

If he had unit tests to show the valid emails, and prove his change wasn’t flagging valid emails as invalid; then I would be more comfortable approving it. But there were no unit tests, and I didn’t understand the change.

Another developer pointed out that the advice for emails is usually just to go for the simple *@*.* validation which translates to; “it must have  some characters, followed by an @ sign, more characters, then a period followed by some characters“.

Email validation is surprisingly complicated, so it’s best having a simple restriction just to filter out data-entry errors. Having complex restrictions can then exclude people’s valid email addresses and you definitely don’t want to do that!