You’re Only As Good As Your Last Backup

… is a necessary rule of thumb for computer-based knowledge & design workers. But add the lesson of cloud computing:

Backups: If you don't have 3 copies, you aren't serious.

The standard redundancy for cheap cloud storage options is 3 copies. Anything less is reduced redundancy, sold at discount. You should have at least 2 backups, for instance both a home backup disk and a cloud drive or repo.

A big win, when you plan for multiple copies, is that you no longer need any of them to be highly reliable. What matters more is, how fast can you make another copy if one copy goes down?

.Net and Asp.Net on MacOs & Mono instead of Windows (using Visual Studio or JetBrains Rider)

Mono goes a long way in running code written for .Net on Windows. It is all very much easier if you either start with cross-platform in mind, or if you move to .Net Core; but even for existing .Net Framework projects mono can run runs most things including Asp.Net.

Here's my checklist from a couple of years of opening .Net Framework solution files on a Mac and finding they don't build first time.

Most of these require you to edit the .csproj file to make it cross-platform, so a basic grasp of msbuild is very helpful.

  1. For AspNet: inside the PropertyGroup section near the top of the csproj file, add an element:

    <WebProjectOutputDir Condition="$(WebProjectOutputDir) == '' AND $(OS) == 'Unix' ">bin/</WebProjectOutputDir>

    Use this if you get a 'The “KillProcess” task was not given a value for the required parameter “ImagePath” (MSB4044)' error message; or if the build output shows you are trying to create files in an top-level absolute /bin/ path.

  2. For AspNet: Add Condition="'$OS'!='Unix'" to the reference to Microsoft.Web.Infrastructure.dll AND delete the file from the website bin directory.

    <Reference Condition="'$OS'!='Unix'" Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
    <Private>True</Private>
    <HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
    </Reference>
  3. For all project types—but, only if you need to use the netCore dotnet build tooling to build an NetFramework project on unix. mono's msbuild does not need this. Add this section somewhere in the csproj file (I put it right at the bottom), to resolve NetFramework4 reference paths:

    <PropertyGroup Condition="$(TargetFramework.StartsWith('net4')) and '$(OS)' == 'Unix'">
    <!-- When compiling .NET SDK 2.0 projects targeting .NET 4.x on Mono using 'dotnet build' you -->
    <!-- have to teach MSBuild where the Mono copy of the reference asssemblies is -->
    <!-- Look in the standard install locations -->
    <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/Library/Frameworks/Mono.framework/Versions/Current/lib/mono')">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono</BaseFrameworkPathOverrideForMono>
    <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/usr/lib/mono')">/usr/lib/mono</BaseFrameworkPathOverrideForMono>
    <BaseFrameworkPathOverrideForMono Condition="'$(BaseFrameworkPathOverrideForMono)' == '' AND EXISTS('/usr/local/lib/mono')">/usr/local/lib/mono</BaseFrameworkPathOverrideForMono>
    <!-- If we found Mono reference assemblies, then use them -->
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net40'">$(BaseFrameworkPathOverrideForMono)/4.0-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net45'">$(BaseFrameworkPathOverrideForMono)/4.5-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net451'">$(BaseFrameworkPathOverrideForMono)/4.5.1-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net452'">$(BaseFrameworkPathOverrideForMono)/4.5.2-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net46'">$(BaseFrameworkPathOverrideForMono)/4.6-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net461'">$(BaseFrameworkPathOverrideForMono)/4.6.1-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net462'">$(BaseFrameworkPathOverrideForMono)/4.6.2-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net47'">$(BaseFrameworkPathOverrideForMono)/4.7-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net471'">$(BaseFrameworkPathOverrideForMono)/4.7.1-api</FrameworkPathOverride>
    <FrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != '' AND '$(TargetFramework)' == 'net472'">$(BaseFrameworkPathOverrideForMono)/4.7.2-api</FrameworkPathOverride>
    <EnableFrameworkPathOverride Condition="'$(BaseFrameworkPathOverrideForMono)' != ''">true</EnableFrameworkPathOverride>
    <!-- Add the Facades directory.  Not sure how else to do this. Necessary at least for .NET 4.5 -->
    <AssemblySearchPaths Condition="'$(BaseFrameworkPathOverrideForMono)' != ''">$(FrameworkPathOverride)/Facades;$(AssemblySearchPaths)</AssemblySearchPaths>
    </PropertyGroup>
  4. For projects that have lived through C# evolution from C# 5 to C# 7: You may need to remove duplicate references to e.g. System.ValueTuple. Add Condition="'$(OS)' != 'Unix'" to the reference. This applies to Types that MS put on NuGet.org during the evolution. idk why msbuild builds without complain on Windows but not on Unices.
    Example:

    <Reference Condition="'$(OS)' != 'Unix'" Include="System.ValueTuple, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
    <HintPath>..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
    </Reference>
  5. For References to Microsoft.VisualStudio.TestTools.UnitTesting: Add a nuget reference to MSTEST V2 from nuget.org and make it conditional on the OS

    <ItemGroup Condition="'$(OS)' == 'Unix'">
    <Reference Include="MSTest.TestFramework" Version="2.1.1">
    <HintPath>..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
    </Reference>
    <Reference Include="coverlet.collector" Version="1.3.0" >
    <HintPath>..\packages\coverlet.collector.1.3.0\build\netstandard1.0\coverlet.collector.dll</HintPath>
    </Reference>
    </ItemGroup>

    Note this will only get you to a successful build. To run the tests on unix you then have to download and build https://github.com/microsoft/vstest and run it with e.g.
    mono ~/Source/Repos/vstest/artifacts/Debug/net451/ubuntu.18.04-x64/vstest.console.exe --TestAdapterPath:~/Source/Repos/vstest/test/Microsoft.TestPlatform.Common.UnitTests/bin/Debug/net451/ MyTestUnitTestProjectName.dll.

  6. Case Sensitivity & mis-cased references
    Windows programmers are used to a case-insensitive filesystem. So if code or config contains references to files, you may need to correct mismatched casing. Usually a 'FileNotFoundException' will tell you if you have this problem.

  7. The Registry, and other Permissions
    See this post for more: https://www.cafe-encounter.net/p1510/asp-net-mvc4-net-framework-version-4-5-c-razor-template-for-mono-on-mac-and-linux

Using the command line

It is helpful to be somewhat familiar with microsoft docs on MSBuild Concepts since msbuild will be issuing most of your build errors. If you have installed mono then you can run msbuild from the command line with extra diagnostics e.g.

msbuild -v:d >> build.log

you can also run web applications from the command just by running

xsp

from the project directory.

Original Text from 2011

For reasons best not examined too closely I switch between between Mac and PC which, since I earn my crust largely with .Net development, means switching between Visual Studio and MS.Net and MonoDevelop with Mono.

Mono is very impressive, it is not at all a half hearted effort, and it does some stuff that MS haven't done. But when switching environments, there's always the occasional gotcha. Here are some that have got me, and some solutions.

  • Gotcha: Linq Expressions don't work on Mono?
    Solution: Add a reference to System.Core to your project.
  • Question: What version of NUnit is built in to mono?As of Feb 2011, it's nunit 2.4.8.

The Isomorphism is not the Terrain

—Draft—

We do not often think of mathematical models as tools so much as the embodiment of a theory. We take formulae such as f=ma to be the theory, not a tool for understanding the theory. Yet mathematical formalisms are chosen for their user-friendliness —their tractability and solvability— just as much as for their correctness, which suggests that theories which rely on them may be calculable yet less than true.

Shannon's Information Theory, for instance, provided a tractable solution to the problem of what is the very best rate of message transfer we can achieve over a wire, and has been so widely re-used one might think that all the world's an abstract communication channel.

By contrast, Sundman's 1912 infinite series solution to the three-body problem languishes in obscurity not because it is wrong, but because it is incalculable. Instead, dozens and hundreds of models of special cases of the 3-body problem have been published since then, each having the virtue of user-friendliness: you can actually use them to calculate something.

With a theory such as Shannon's, usability leads to enthusiastic adoption and enthusiastic adoption leads to a sense of well-being and belief we can solve all the things with this one simple trick.

What it does not lead to, is a careful enumeration of assumptions made in the adoption of a model.

This is fine for the engineer who just wants to calculate and get a result. It is less fine when the scientist enthusiastically declares that their mathematical model solves all the philosophical problems too.

For the philosophical problems are rarely captured in the mathematical model. They are more usually either captured or carefully avoided in some well-worded definitions and assumptions in the preamble and the prerequisites of the model.

For instance, Shannon defines a measure of information: “If the number of messages in the set [of all possible message you might want to send] is finite then this number or any monotonic function of this number can be regarded as a measure of the information produced …”

The monotonic function chosen is the logarithm and leads to a definition of Shannon Information as the negative log probability of choosing that message out of all possible messages. This definition has been extremely usable because it is tractable: you can compute with it.

Sadly it has only a tangential relationship to the meaning of “information”, as Shannon noted: “Frequently messages have meaning … These semantic aspects of communication are irrelevant to the engineering problem.”

Imagine for instance, you drive from Durham to Barnard's Castle and lost at a crossroads, ask a farmer for directions. He draws his fair 6-sided die from a pocket, tosses it, and reports, “It's a 6.”

Per the mathematical model, the farmer is rather informative. He has conveyed 2.6 shannons of information. Had he instead said, “Ah yes, for Barnard's Castle you want to turn left here” that would have conveyed barely 2 shannons of information (less, if “do a U-turn” was not on the table) and so been less informative.

The model is not reality. Information in the model is not information in the real world. Rather, information in the model is something that is isomorphic to something that is quite close to information in the real world.

The model definition of information — negative log likelihood — is certainly good and very usable for a definition of the maximum possible information rate achievable over a communication channel. It has also turned out to be very … usable … in related applications. Because the idea of an abstract communication channel can be used for a wide range of natural phenomena, and so a theory of them is widely useful.

But usability of a mathematical model leads to enthusiasm and enthusiasm may lead to completely ignoring niceties such as the relationship between the model and reality.

We could go with the flow and allow the model definition of information to override our previous understanding, and declare that information is negative log likelihood of selecting a particular message from a finite set of messages. It's tractable so it's true. After all, no-one likes to be stuck with intractable problems. Sundman's result was big at the time, but no-one remembers him now.

A mathematical model is a structure. A particular structure is picked out because it is user-friendly and because an isomorphism exists which maps onto it something that is close to something we are interested in. Shannon information is tangentially close to real information: there's a vanishingly small place where it's an exact match, a fuzzier area where it's very close and lots of places, such as en route to Barnard's Castle, where it's just wrong.

It seems an elementary mistake to say, “this structure lets us calculate stuff and therefore reality is exactly like this” yet it happens all the time. As people learn a result calculated using information theory, or Turing computability, or Bayes theorem, they go into the world convinced they're seen the light.

They've seen the light of a structure that is isomorphic to something that is close to something that interests us. They may never notice the assumptions and definitions required for the structure to count as a map of reality.

The isomorphism is not the terrain.