Monday, 23 March 2026

Why use a code formatter

For years I've used the Delphi code formatter (CTRL+D) for the reasons below and still cannot understand why some developers don't use it and spend time manually indenting, adding removing spaces etc. When developers don't use code formatters (that are setup the same) it leads to messy codebases, inconsistent code, arguments about spacing and formatting and waists time.

Here are the Pros and Cons of using a code formatter.

The Pros: Why Formatters are Essential

  • Drastically Improved Code Reviews: Without a formatter, pull requests often get bogged down by "nitpick" comments like, "Can you add a space here?" or "Please use single quotes." Formatters eliminate this entirely. Code reviews can focus 100% on logic, architecture, and security.

  • Zero Cognitive Load: Formatting manually wastes time. A developer should be thinking about solving complex business problems, not counting indentation spaces or calculating line lengths.

  • A Unified Codebase: A codebase should read as if it were written by a single person. When multiple developers use their own styles, the code becomes visually jarring and harder to read. Formatters create a predictable standard.

  • Fewer Merge Conflicts: Inconsistent formatting is a massive driver of Git merge conflicts. If Developer A uses tabs and Developer B uses spaces, touching the same file will trigger massive conflicts just based on invisible whitespace.

  • Faster Onboarding: New developers don't have to read a 10-page style guide to understand how the team formats code. They just hit save, and the tool does it for them.

The Cons: Why Some Developers Resist

While the pros heavily outweigh the cons, it is helpful to understand why some developers might be pushing back:

  • Loss of Contextual Readability: Formatters apply rigid rules. Occasionally, a developer might format a complex array or mathematical matrix in a specific, non-standard way to make it more readable for humans. A formatter will aggressively crush this custom formatting back into the standard shape. (Workaround: Most formatters have a // ignore comment you can use for specific blocks of code).

  • Initial Configuration Arguments: Setting up a formatter often forces a team to have the dreaded "Tabs vs. Spaces" or "80 vs. 120 character line limit" arguments. Some developers hate giving up their personal preferences.

  • Git Blame Pollution: If you introduce a formatter to an older codebase, the first run will touch almost every file. This means git blame will show the person who ran the formatter as the last author of every line, obscuring the actual author. (Workaround: You can use a .git-blame-ignore-revs file to tell Git to ignore the massive formatting commit).

  • The "Loss of Control" Feeling: Some developers take deep pride in the craftsmanship of manually crafting their code. An automated tool re-arranging their work can feel intrusive to them.


Wednesday, 18 February 2026

SQL Server - How to capture database errors

One very useful addition to a database I have found recently is to capture database errors in a try...catch block and storing the information in a table. Here is what I did:

Table to store the error information:

CREATE TABLE dbo.DBErrors (
  DBErrorID INT IDENTITY
 ,Raised DATETIME NULL CONSTRAINT DF_DBErrors_Raised DEFAULT (GETDATE())
 ,Number INT NULL
 ,Severity INT NULL
 ,StateNumber INT NULL
 ,StoredProcedure NVARCHAR(128) NULL
 ,Line INT NULL
 ,ErrorMessage NVARCHAR(4000) NULL
 ,CONSTRAINT PK_DBErrors PRIMARY KEY CLUSTERED (DBErrorID)
) ON [PRIMARY]

Then I wrote a stored procedure to write to the table:

CREATE PROCEDURE dbo.DBErrorInsert
AS
BEGIN
DECLARE @DBErrorsExist bit;
  SET NOCOUNT ON;
  
  SELECT TOP (1) @DBErrorsExist = TableExists FROM dbo.efn_TableExists('DBErrors');
IF (@DBErrorsExist = 1)
BEGIN
INSERT INTO DBErrors (Number, Severity, StateNumber, StoredProcedure, Line,   ErrorMessage) VALUES ( 
ERROR_NUMBER(),  
ERROR_SEVERITY(),  
ERROR_STATE(),  
ERROR_PROCEDURE(),  
ERROR_LINE(),  
ERROR_MESSAGE());
    RETURN -2;
END
  ELSE
  BEGIN
    RETURN -1;
  END;
END;

Then where I wanted to capture any errors i.e. in a stored procedure I did the following:

BEGIN TRY
  ... Stored proc code
END TRY
BEGIN CATCH
  EXEC dbo.DBErrorInsert;
END CATCH

When an error occurs in the try...catch block it writes the error information including the line the error was triggered to a record in the table.



Tuesday, 17 February 2026

SQL Server - List all fixed length fields in a database

I noticed that a field in a database had been set to a nchar(), this means it's a fixed length and in a result query had trailing spaces. The 2 options I had were to change the field type to nvarchar() or add a RTRIM() to the field and alias it. To identify any other fields that were like this I ran the following query:

SELECT 
    TABLE_SCHEMA,
    TABLE_NAME, 
    COLUMN_NAME, 
    DATA_TYPE, 
    CHARACTER_MAXIMUM_LENGTH AS Defined_Length
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE IN ('char', 'nchar')
ORDER BY TABLE_NAME;

Friday, 13 February 2026

Mouse Wheel and TScrollBox

We had an issue where there was a TScrollbox on a form and the mouse wheel would not do the vertical scroll. The simplest solution I found for this was to do the following in the forms 'OnMouseWheel' event.

if MyScrollBox.BoundsRect.Contains(MyScrollBox.Parent.ScreenToClient(MousePos)) then
begin
  MyScrollBox.VertScrollBar.Position := MyScrollBox.VertScrollBar.Position -                   WheelDelta;
  Handled := True;
end;