How single page application works

Single page applications use hash-based or pushState navigation to support back/forward gestures and bookmarking. The best known example probably is Gmail but now there are other too. If you’re not familiar with how that technique works, here is a brief explanation;

For hash-based navigation, the visitor’s position in a virtual navigation space is stored in the URL hash, which is the part of the URL after a ‘hash’ symbol (e.g., /my/app/#category=shoes&page=4). Whenever the URL hash changes, the browser doesn’t issue an HTTP request to fetch a new page; instead it merely adds the new URL to its back/forward history list and exposes the updated URL hash to scripts running in the page. The script notices the new URL hash and dynamically updates the UI to display the corresponding item (e.g., page 4 of the “shoes” category).

This makes it possible to support back/forward button navigation in a single page application (e.g., pressing ‘back’ moves to the previous URL hash), and effectively makes virtual locations bookmarkable and shareable.

pushState is an HTML5 API that offers a different way to change the current URL, and thereby insert new back/forward history entries, without triggering a page load. This differs from hash-based navigation in that you’re not limited to updating the hash fragment — you can update the entire URL.

Debounce and Throttle in JavaScript

Debounce and throttle are two concepts that we can use in JavaScript to increase the control of our function executions, specially useful in event handlers.

Both techniques answer the same question “How often a certain function can be called over time?” in different ways:

  • Debounce: Think of it as “grouping multiple events in one”. Imagine that you go home, enter in the elevator, doors are closing… and suddenly your neighbor appears in the hall and tries to jump on the elevator. Be polite! and open the doors for him: you are debouncing the elevator departure. Consider that the same situation can happen again with a third person, and so on… probably delaying the departure several minutes.
  • Throttle: Think of it as a valve, it regulates the flow of the executions. We can determine the maximum number of times a function can be called in certain time. So in the elevator analogy.. you are polite enough to let people in for 10 secs, but once that delay passes, you must go!

Event handlers without debouncing or throttling are like one-person-capacity elevators: not that efficient.

Use cases for debounce

Use it to discard a number of fast-pace events until the flow slows down. Examples:

  • When typing fast in a textarea that will be processed: you don’t want to start to process the text until user stops typing.
  • When saving data to the server via AJAX: You don’t want to spam your server with dozens of calls per second.

Use cases for throttle

Same use cases than debounce, but you want to warranty that there is at least some execution of the callbacks at certain interval

  • If that user types really fast for 30 secs, maybe you want to process the input every 5 secs.
  • It makes a huge performance difference to throttle handling scroll events. A simple mouse-wheel movement can trigger dozens of events in a second. Even Twitter had once problems with scroll events, so learn from others mistake and avoid this easy pitfall.

Here is visual guide to these concepts.

Resource

https://redd.one/blog/thinking-in-functions-higher-order-functions

SQL Cursor – Forward Only vs Fast Forward

Lets take a look at two queries using CURSORS, the first one will use the FORWARD_ONLY type cursor, and the second will use the FAST_FORWARD type cursor. These two types sound very similar, but perform quite differently.

DECLARE @firstName as NVARCHAR(50);
DECLARE @middleName as NVARCHAR(50);
DECLARE @lastName as NVARCHAR(50);
DECLARE @phone as NVARCHAR(50);
DECLARE @PeoplePhoneCursor as CURSOR;
 
SET @PeoplePhoneCursor = CURSOR FORWARD_ONLY FOR
SELECT TOP 10 FirstName, MiddleName, LastName, PhoneNumber
  FROM person.Person p
 INNER JOIN person.personphone pp on p.BusinessEntityID = pp.BusinessEntityID;
 
OPEN @PeoplePhoneCursor;
FETCH NEXT FROM @PeoplePhoneCursor INTO @firstName, @middleName, @lastName, @phone;
 WHILE @@FETCH_STATUS = 0
BEGIN
     PRINT ISNULL(@firstName, '') + ' ' +
           ISNULL(@middleName, '') + ' ' +
           ISNULL(@lastName, '')  +
           ' Phone: ' + ISNULL(@phone, '') ;
     FETCH NEXT FROM @PeoplePhoneCursor INTO @firstName, @middleName, @lastName, @phone;
END
CLOSE @PeoplePhoneCursor;
DEALLOCATE @PeoplePhoneCursor;

Now for the FAST_FORWARD CURSOR example. Notice only one line has changed, that’s the line that says “SET @PeoplePhoneCursor = CURSOR FAST_FORWARD FOR”.

DECLARE @firstName as NVARCHAR(50);
DECLARE @middleName as NVARCHAR(50);
DECLARE @lastName as NVARCHAR(50);
DECLARE @phone as NVARCHAR(50);
DECLARE @PeoplePhoneCursor as CURSOR;
 
-- HERE IS WHERE WE SET THE CURSOR TO BE FAST_FORWARD
SET @PeoplePhoneCursor = CURSOR FAST_FORWARD FOR
SELECT TOP 10 FirstName, MiddleName, LastName, PhoneNumber
  FROM person.Person p
 INNER JOIN person.personphone pp on p.BusinessEntityID = pp.BusinessEntityID;
 
OPEN @PeoplePhoneCursor;
FETCH NEXT FROM @PeoplePhoneCursor INTO @firstName, @middleName, @lastName, @phone;
 WHILE @@FETCH_STATUS = 0
BEGIN
     PRINT ISNULL(@firstName, '') + ' ' +
           ISNULL(@middleName, '') + ' ' +
           ISNULL(@lastName, '')  +
           ' Phone: ' + ISNULL(@phone, '') ;
     FETCH NEXT FROM @PeoplePhoneCursor INTO @firstName, @middleName, @lastName, @phone;
END
CLOSE @PeoplePhoneCursor;
DEALLOCATE @PeoplePhoneCursor;

The FORWARD_ONLY CURSOR takes 4 times the time as the FAST FORWARD CURSOR, and the number continues to widen as the number of times the cursor loops is executed.

FAST FORWARD CURSORS are usually the fastest option with SQL Server. There may be cases where another option may work better, but the FAST FORWARD CURSOR is a good place to start if you must use a CURSOR.

The best practice is to avoid cursor but sometime they are inevitable. The alternatives could be temp tables, while loops etc.

Case sensitive search on a case insensitive sql server

Recently I had a problem where i need to search for;

  1. Foo
  2. foo

SQL Server default behavior is to do case insensitive search. so if run a query like this;

IF OBJECT_ID('tempdb..#FooTable') IS NOT NULL DROP TABLE #FooTable
SELECT x.* 
INTO #FooTable
FROM
(
	SELECT 1 AS Id, 'Foo' AS UserName
	UNION ALL
	SELECT 2 As Id, 'foo' AS UserName
) x

I will get two records back.

To do a case sensitive search, do this;

SELECT UserName
FROM #FooTable
WHERE 1=1
AND UserName = 'foo' COLLATE SQL_Latin1_General_CP1_CS_AS

Result would be;

For join operations, let’s create another table;

--Now add a second table, say salary
IF OBJECT_ID('tempdb..#FooSalaryTable') IS NOT NULL DROP TABLE #FooSalaryTable
SELECT x.* 
INTO #FooSalaryTable
FROM
(
	SELECT 1 AS Id, 'Foo' AS FooId, 4000 AS UserSalary
	UNION ALL
	SELECT 2 As Id, 'foo' As FoodId, 6000 AS UserSalary
) x

SELECT * FROM #FooSalaryTable

This is join query;

--example with join
SELECT 
	x.UserName, y.UserSalary
FROM #FooTable x
JOIN #FooSalaryTable y on x.UserName = y.FooId COLLATE SQL_Latin1_General_CP1_CS_AS
WHERE 1=1
AND x.UserName = 'foo' COLLATE SQL_Latin1_General_CP1_CS_AS

and results;

For more info, follow these articles;

https://stackoverflow.com/questions/1831105/how-to-do-a-case-sensitive-search-in-where-clause-im-using-sql-server

https://www.mssqltips.com/sqlservertip/1032/case-sensitive-search-on-a-case-insensitive-sql-server/

https://stackoverflow.com/questions/17172175/add-column-to-temp-table-invalid-column-name-decimal

Customizing ADO

This article is for the basic process template. The hierarchy is Epic, Issue and Task. Each level in this hierarchy has a page. Keep in mind that page follows a 3 section layout, Detail, Planning and Related work.

Epic customization Click on three dots (…) on the right side in Epic.

This will show following page;

Click on New field. You will get to following page;

The frequently used fields are already listed in “Use an existing field” but if you want to create a new one, you can use “Create a field”.  More important, on the left side of navigation, pay attention to Layout section. This is where you can decide where to store this field; left, center or right.

Some standard fields that can be used in these pages are;

Risk, Effort, Business Value, Start Date, Target Date, T-shirt sizing, Story points, Activity, Original Estimate, Remaining Work, Completed Work.

Resources

https://learn.microsoft.com/en-us/azure/devops/organizations/?view=azure-devops

https://learn.microsoft.com/en-us/azure/devops/organizations/settings/work/customize-process-work-item-type?view=azure-devops#what-you-can-customize