After many years using (and enjoying) Git, I had to start using Subversion again on a daily basis.

Git treats ignores on a regular file (.gitignore, whose rules are applied both to the same folder and to all subfolders), while Subversion treats ignores as an svn:property, which makes it harder to add new filemasks to the ignore list.

Using TortoiseSvn you can just click on the “add to ignore list”, but on command line you don’t have that.

This PowerShell function helps you on that. It will extract the svn:ignore property on any folder, include a new pattern to the list of ignores, and update the property. Enjoy!

function Svn-Add-Ignore
{
   param(
     [Parameter(Position=0,mandatory=$true)]
     [string] $folder,
     [Parameter(Position=1,mandatory=$true)]
     [string] $filemask
   )

   if (( Test-Path $folder) -eq $False)
   {
       Write-Host "Path $folder not found" -for red
       Exit 1
   }
   
   $ignores = (svn propget svn:ignore $folder)
   if($ignores)
   {
      $ignores = ($ignores -join "`n" | Out-String).Trim()   # convert multiple lines to single multiline string
      $ignores = $ignores + "`n" + $filemask
   }
   else
   {
      $ignores = $filemask
   }
   svn propset svn:ignore $ignores $folder
}

Sample usage:

Svn-Add-Ignore .\ "bin"
Svn-Add-Ignore .\ "obj"
Svn-Add-Ignore .\ ".vs"
Svn-Add-Ignore .\ "*.user"

Enterprise Software, Custom Development, and SaaS

Enterprise Software companies (like Oracle, Microsoft, SAP, etc) have their value proposition centered on the products they own, but they usually sell professional services attached to those products, aimed at training, support, product configuration, and some degree of customization. They will charge tons of money for those professional services, but their core value still resides in their products. You can purchase Oracle Database or Siebel CRM, and they will gladly customize that for you for a few hundreds of thousands of dollars, but they surely won’t modify anything in the core of their product, no matter how much you beg (or pay) for that.

In the opposite way, Custom Development companies (including Consultancy companies which offer custom development services, like Accenture or Tata Consulting Services), they provide their value by doing exactly what their customers want, usually backed by a team of senior consultants/engineers, and some well-established processes. Their value proposition is that they have a large network of consultants who can help in any problem you may have, and you also have someone to blame in case things go wrong.

Custom Development companies don’t really care on how much customization you ask for. For anything that you ask for, they will overcharge you, and happily develop it for you. For those companies, body shopping is exactly what they sell, and their technology or product (if any) is definetly not relevant to their business. If by any chance they already have a codebase that they can reuse(*), they won’t bother to completely modify (or even rewrite it) if you ask for that, because that’s what they are there for. Your codebase won’t be reused for any other customer because it´s probably so tied to your business that it won’t make sense to anyone else. Similarly to Enterprise vendors, Custom Development companies will also cost you an arm and a leg. Similarly, they also have large costs for each new customer.

(*) I won’t call it a product - custom development companies and consultancies do not have products, even if they can reuse their past projects to some extent.

Finally, there are the Software-as-a-Service companies, which are based on economies of scale, where each new customer should increase their revenue at some very low marginal costs. The value proposition for those companies is usually their technology, combined with their low adoption barriers, the lack of vendor lock-in, and the aforementioned scalability. For a “pure” SaaS company, the more customers you have the better - but only as long as they don’t bother you too much or give you too much work, because the major income source is NOT body shopping, but the subscription fees (recurring revenue).

Although SaaS vendors tried hard to commoditize application funcionalities for their customers, each customer is different and they are not happy with out-of-the-box solutions - they need customizations and extensions. The problem is that SaaS sits between Custom Development and Enterprise Software, in the sense that they can modify their core products for their customers, but they also must maintain a stable product codebase which should evolve for all customers, since they are responsible for hosting and maintaning their customers. Unfortunately most SaaS companies can’t find the correct balance between the customizations maintenance and the product management.

Let’s Play Microsoft

Developing a highly configurable and truly extensible product is very difficult and expensive. Making something configurable has a fixed cost that will only make up for when you have a large number of customers that will need that configuration. Making everything configurable not only has a large cost, but is also pointless since you don’t want to sell a framework (much less a compiler), but a stable and well-defined product. Making something extensible to end-users requires a well-designed plugin architecture (or a well designed API) and that comes with a price tag which usually is only compensated when you have a huge number of customers. Large companies like Microsoft and Oracle have teams with hundreds of engineers working exclusively on Product Development (or R&D like you learn in MBA), and they still have limitations. A SaaS company cannot affort that model, unless it has tens of thousands of customers willing to pay for non-commodity SaaS.

I’ve worked for a few years in a SaaS company that followed that Enterprise model and that was very unproductive. When a customer requested something to the Projects/Consultancy department, the request was reviewed by a consultant, which usually had to discuss that with the Product Development team, which would evaluate if that request made sense to be incorporated in the product. In case it didn’t fit into the product they would (at best case) provide a new extension point so that the Projects team could develop a new extension and plug that into a DLL into the product. Does this sound reasonable? If it sounds reasonable for you, it’s because you didn’t picture that most of the requests were cosmetic changes like: remove this button, rename that label, change that color, make this field read-only, etc. All those small changes had to pass through many areas. THAT was costly.

Even for non-trivial things (like pricing rules and discount rules), each customer had rules so specific that the product configurations were not enough for the majority of them. It’s obvious that there were some changes that were possible without requiring a product modification (afterall there was a whole product development team for that), but usually that wasn’t the rule, but the exception. As as consequence of that structure, we could only reach enterprise customers (which usually are the ones who have more money than sense).

At some point the product team also decided to develop their own scripting language (VBA-like). Yes, that’s right - a SaaS company, with no more than a hundred customers, decided to develop their own scripting language, for internal use, because no one could touch the holy product, which was supposed to be so well designed that no educated developer would be able to modify the source code without fucking up everything.

If your company is doing like that, remember: You are not Microsoft. In other words, don’t develop a plugin architecture or a scripting language or a complex API unless you are either a Platform as a Service company (like SalesForce) or unless you have tens of thousands of customers who will extend your product on their own. If you are developing developer-tools for internal use, not only you are not adding value to the company, but also your product managers should leave technology passion aside and start thinking about business. Microsoft cannot develop automation for the worksheets of all their customers, SAS cannot develop ABAP customizations for all their customers, but your SaaS company can customize the instance of each customer, as long as you don’t want to make commodity SaaS.

There is a similar mistake which I’ve seen a few times that is to completely ignore that your product should solve some very clear business needs, and turn your product into a general tool for creating any program, like a 4th generation programming language. Unless you are competing with Microsoft (Visual Studio) or Borland, and unless you are trying to make your own GeneXus / FoxPro / Informix / Clipper/ Progress / etc, then please focus on your product, with some clear business value, and not on applications to make applications.

If you are a SaaS company and your engineers love building compilers and development tools, you should either teach them Business 101 or hire a results-oriented team.

Independent Codebases for each Customer

When you run a multi-tenant SaaS application, all your customers run on the same instance (and consequently on the same codebase). A multi-tenant application must surely provide some level of configuration: a customer can probably add their name, their logo, their colors and visual identity, and probably set up the users, roles and permissions. But the codebase is shared among all customers, so unless you have a quite elaborated plugin architecture (which has a price tag), the customizations are usually expensive and with lots of limitations. Remember: You are not Microsoft.

On the other side, when you run single-tenant applications (each customer with a dedicate instance - not necessarily with his own server), you can have an independent codebase for each customer, and that provides an unlimited level of customization.

Perfect. So I’ll run all my customers in single-tenant instances, and each one will have their own codebase repository, totally disconnected from my baseline product. If that works for Accenture, it can work for me, right?

Not really. As I explained before, Consultancy Body Shops focus is selling man-hour projects. They don’t have a core product, and they don’t care about your source code. Also, they do not host your software. A SaaS company has a core product which is their most valuable asset, they host the application of their customers, and they should provide them with updates and fixes. They cannot just copy the codebase for each customer, customize it, and keep that code running unattended. Well, actually they can, but that’s not scalable, and they would be leaving money on the table: Customers need upgrades, customers need bug fixes, customers don’t want to depend on a single engineer who understands their customizations. When you have a SaaS application with more than a few dozens of customers, meeting all those requirements with independent codebases is either impossible or very expensive and naive.

Supposing that you are brave enought to run your customers with independent codebases, as soon as you reach a few hundred customers, every bug which is discovered and fixed will be difficult to be applied to each of those hundreds of customers, not only because you would have to modify a hundred different places, but also because those projects by now are probably very different from each other. Each new feature developed for one customer (or for the product) won’t be easily available to existing customers. Each new engineer who joins your team will have a learning curve trying to understand the customizations for that client. Everytime some engineer goes on vacation, the person who covers him will have a hard time understanding the new project. As time goes by, it becomes almost impossible to distinguish between what was part of your original product and what was a client customization. So you’ll end up with hundreds of different loosely-related applications, and you lose your most valuable asset: having a coherent product that is mastered by your engineers.

Remember, you don’t want to be as huge as Microsoft - you want to scale to as many customers as possible with as few engineers as possible.

Bottom line is: the major problem in managing a SaaS Product is the tradeoff between Extensibility vs Maintenance.

Extensibility for SaaS Companies who don’t want to be Microsoft

In my next posts I’ll describe some ideas for developing an architecture that is a balance between the “Holy Product” model and the “Repository per Client” model. You’ll be able to offer product enhancements and upgrades to your customers, while being able to completely customize the product programatically for each customer. Customizing the application for each customer will be easier than ever, and that translates into less costs for your customers and more revenue for you.

I’ll use my favorite technology stack for those posts (C#, SQL Server and Entity Framework) but you should be able to adapt most ideas to any other language/framework. I’ll explore how some tools/technologies/paradigms can be used and how some of them don’t make sense or are not practical. On the top of my head I can think of topics like branches per customer, OOP inheritance, publish-subscriber pattern, Dependency Injection, partial classes, code generation, but probably I’ll add more topics as I write the next articles and as I develop my code samples.

When I was a kid, most computers here in Brazil were using US QWERTY keyboards, and with some help from this nice teacher (on my MS-DOS 5.0) I taught myself typing on that keyboard layout.

One day, someone who should probably be a strong nationalist (or maybe a lobbyist, or maybe just someone suffering from NIH syndrome) invented the Brazilian Portuguese Keyboard and all retailers and companies started using that new standard. I resisted for many years, and remained buying myself only QWERTY keyboards, until I finally gave up and embraced the Brazilian keyboard, since it was getting harder to buy a QWERTY keyboard in Brazil.

The problem is that although we have created our own power plug standard, our own digital TV standard, our own TV middleware and even our own analog color TV standard in the 70s, we still have communication and interaction with other countries who follow other standards.
(If you don’t know Brazil, I must explain that all those standards are NOT about nationalism, patriotism or about Not-Invented-Here syndrome - it’s all about spending lots of public funds so that our politicians can divert huge amounts of money into their own pockets)

But jokes aside (no, the 3 standards were not a joke), sometimes we use Laptops that were purchased abroad (that don’t have our keyboard layout), and we share servers that are hosted or used by people in other countries. That keyboard mismatch usually happens when you are using some keyboard to control a computer which is also controlled by people with different keyboards.

Windows allows you to set-up multiple languages and multiple keyboards for each language, and you can also toggle keyboards/languages with a hotkey (default alt+shift). The problem is that if you type as fast as Mavis taught me to, probably you should frequently toggle keyboards by mistake as I do.

To solve that, I decided that I would disable the hotkey for toggling keyboards, and more than that, I decided to create a Powershell script that would completely remove one keyboard/language and configure another one.

The script below (just save as .ps1 extension) will toggle (uninstalling and reinstalling the other) between Portuguese Brazil ABNT2 keyboard (10416) and US Qwerty (409), but always keeping English language (409).

# This scripts toggles keyboards between "Keyboard Portuguese Brazil ABNT2" and "US Qwerty"
# based on https://technet.microsoft.com/en-us/library/hh852168.aspx
# and https://github.com/fdcastel/setup-fdcastel/blob/master/Setup-First.ps1

$currentLangAndKeyboard = (Get-WinUserLanguageList).InputMethodTips

if ($currentLangAndKeyboard -eq "0409:00000409")
{
  $langList = New-WinUserLanguageList en-US
  $langList[0].InputMethodTips.Clear()
  $langList[0].InputMethodTips.Add('0409:00010416') # English (United States) - Keyboard Portuguese Brazil ABNT2
  Set-WinUserLanguageList $langList
}
Else
{
  $langList = New-WinUserLanguageList en-US
  $langList[0].InputMethodTips.Clear()
  $langList[0].InputMethodTips.Add('0409:00000409') # English (United States) - US Qwerty
  Set-WinUserLanguageList $langList
}



# If you want to have two languages (or keyboards) at same time, just .Add() both, but disable toggle language hotkey - http://answers.microsoft.com/en-us/windows/forum/windows_xp-desktop/how-can-disable-switch-between-different-input/dba24e17-ad93-46e9-9775-baf097d550ee?auth=1
# $HKCUKeyboardLayoutToggle = 'HKCU:\Keyboard Layout\Toggle\'
# Set-ItemProperty -Path $HKCUKeyboardLayoutToggle -Name 'Language Hotkey' -Value 3
# Set-ItemProperty -Path $HKCUKeyboardLayoutToggle -Name 'Layout Hotkey' -Value 3
# Set-ItemProperty -Path $HKCUKeyboardLayoutToggle -Name 'Hotkey' -Value 3

As I said, I wanted to have only one language at a time to avoid the language hotkey, but later I realized that I could have just disabled that annoying hotkey. If you want to just disable the hotkey, just uncomment the final block in the script, which will add some keys to your registry. And if you want to use a powershell script to configure multiple keyboards (simultaneously), just call InputMethodTips.Add for each language/keyboard you want to add.