When needing to make a change to a Revit model, we need to use a transaction.

I find it convenient for the main code to not have transactions, but for the methods that are called inside of that main code to have the transactions. This way, when reading the main, you can focus on the logic of the that specific command.

Another thing I would like to mention about transactions is that sometimes we can get errors when trying to call methods of an object of the model we just created, because we are calling the methods before closing the transaction (a method returns null, even you are working with a valid object). This can be prevented with the approach mentioned above: atomic methods, each one with its transaction, and a clean main code.