﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com/blog/</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2012 (c) 2013</copyright><ttl>60</ttl><item><title>My Passover Project: Introducing Rattlesnake.CLR</title><description>&lt;p&gt;Okay, after spending quite a lot of time digging through the leveldb codebase, and with several years of working with RavenDB, I can say with confidence that the CLR make it extremely hard to build high performance server side systems using the CLR.&lt;/p&gt; &lt;p&gt;Mostly, the issues are related to GC and memory. In particular, not having any way to control memory allocation and/or the GC means that we can’t optimize those scenarios in any meaningful way. At the same time, I do &lt;em&gt;not&lt;/em&gt; want to go back to the unmanaged world. As mentioned ,I just came back from a very deep dive into a non trivial C++ codebase ,and while I consider that codebase a really good one, that ain’t to say it is a pleasure to always be thinking about all the stuff that the CLR just takes away.&lt;/p&gt; &lt;p&gt;Therefor, I decided that I’m going to be doing something about it. And Rattlesnake.CLR was born:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Implementing-LevelDB-in-managed-code-and_9F16/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Implementing-LevelDB-in-managed-code-and_9F16/image_thumb.png" width="157" height="161"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The major features of the Rattlesnake.CLR include explicit memory management &lt;em&gt;when&lt;/em&gt; required. Let us say that we know that we are going to be needing some amount of memory for a while, and then all of that can be thrown away. This is extremely common in scenarios such as a web request, pretty much all the memory that you generate during the processing web request can be safely free immediately. In RavenDB’s case, the memory we consume during indexing can be free immediately when we stop indexing. Right now this is a painful process of making sure that we allocate within the same gen0 and hoping that it won’t be too expensive, or that we won’t get a complete halt of the entire server while it is releasing memory. It also make it &lt;em&gt;really&lt;/em&gt; hard to do things like limit the amount of memory your code uses.&lt;/p&gt; &lt;p&gt;Another requirement that I have is that Rattlesnake.CLR should be able to execute existing .NET assemblies without any additional steps. Since I don’t fancy doing ports of stuff that already exists.&lt;/p&gt; &lt;p&gt;In order to handle this scenario with the given constraints, we have:&lt;/p&gt; &lt;blockquote&gt; &lt;div id="codeSnippetWrapper"&gt; &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; var heap = Heap.Create(HeapOptions.None, &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     1024 * 1024,&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     512 * 1024 * 1024);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;using&lt;/span&gt;(MemoryAllocations.AllocateFrom(heap))&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; {&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;    var sb = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;for&lt;/span&gt;(var i = 0; i &amp;lt; 100; i ++ )&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;          sb.AppendLine(i);&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;    Console.WriteLine(sb.ToString());&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;&amp;nbsp; &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; heap.Destroy(); &lt;/pre&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;All the code within the using statement is allocated in our own heap. In line 13, we are destroying all of that memory in one fell swoop.&lt;/p&gt;
&lt;p&gt;There are a few notes about this that we probably should address:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By default, memory allocated by this form is not subject to any form of GC. The idea is that this whole heap is getting released immediately.&lt;/li&gt;
&lt;li&gt;Note that last two parameters for the Heap.Create. The first is the initial size of the heap, and the second is&amp;nbsp; the max size. We now have a real way to actually limit the amount of memory a piece of code will use. This is really important on server applications where avoiding paging is critical.&lt;/li&gt;
&lt;li&gt;For that matter, we can now figure out how much memory a particular piece of code uses, and allocate our resources accordingly.&lt;/li&gt;
&lt;li&gt;You can use multiple heaps at the same time, although only one can be installed as the default allocation at a given point in time.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;There is the explicit heap.GarbageCollect() method that will do GC only on that heap, and which you can schedule at your own convenience.&amp;nbsp; You can have two heaps, and allocate from one while you are GCing from the other. And yes ,that means that GCs using this methods will &lt;em&gt;not&lt;/em&gt; stop the process!&lt;/p&gt;
&lt;p&gt;Memory allocated on the heap is obviously only valid as long as the heap is valid. That means that once the heap is destroyed, you can’t access any of the objects that were created there. This has implications for things like cache. We provide MemoryAllocations.AllocateOnGlobalHeap&amp;lt;T&amp;gt;(args) method to force you to use the global heap, instead, if you want this memory to be always available and subject to GC.&lt;/p&gt;
&lt;p&gt;This is early days yet, but we already see some really interesting performance improvements!&lt;/p&gt;
&lt;p&gt;How does this work?&lt;/p&gt;
&lt;p&gt;While an early experiment with Rattlensake.CLR was based on the Mono runtime. I quickly decided that I wanted to keep using the MS CLR. Now, it order to handle this I had to do some unnatural things (to say the least), but I think that I even managed to make this a supported option. Essentially, we are using the CLR Hosting API for this. In particular:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ICLRGCManager&lt;/li&gt;
&lt;li&gt;IHostMalloc&lt;/li&gt;
&lt;li&gt;IHostMemoryManager &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;You can use Rattlesnake.CLR like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;.\Rattlesnake.exe Raven.Server.exe&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Just for fun, we also allowed to place limits on the default heap, so you can be sure that you aren’t allocating too much there.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;.\Rattlesnake.exe Raven.Server.exe --max-default-heap-size=256MB&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;We are still running some tests, but this is looking really good. &lt;/p&gt;</description><link>http://ayende.com/blog/161889/my-passover-project-introducing-rattlesnake-clr?key=d79d601a-c67a-4d80-a182-117b2e343aac</link><guid>http://ayende.com/blog/161889/my-passover-project-introducing-rattlesnake-clr?key=d79d601a-c67a-4d80-a182-117b2e343aac</guid><pubDate>Mon, 01 Apr 2013 10:00:00 GMT</pubDate></item><item><title>Hibernating Rhinos Practices: A Sample Project</title><description>&lt;p&gt;I have previously stated that one of the things that I am looking for in a candidate is the actual candidate code. Now, I won’t accept “this is a project that I did for a client / employee”, and while it is nice to be pointed at a URL from the last project the candidate took part of, it is not a really good way to evaluate someone’s abilities.&lt;/p&gt; &lt;p&gt;Ideally, I would like to have someone that has an OSS portfolio that we can look at, but that isn’t always relevant. Instead, I decided to sent potential candidates the following:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Hi,&lt;/p&gt; &lt;p&gt;I would like to give you a small project, and see how you handle that.&lt;/p&gt; &lt;p&gt;The task at hand is to build a website for Webinars questions. We run bi-weekly webinars for our users, and we want to do the following:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Show the users a list of our webinars (The data is here: &lt;a title="http://www.youtube.com/user/hibernatingrhinos" href="http://www.youtube.com/user/hibernatingrhinos"&gt;http://www.youtube.com/user/hibernatingrhinos&lt;/a&gt;)  &lt;li&gt;Show a list of the next few scheduled webinar (in the user’s own time zone)  &lt;li&gt;Allow the users to submit questions, comment on questions and vote on questions for the next webinar.  &lt;li&gt;Allow the admin to mark specific questions as answered in a specific webinar (after it was uploaded to YouTube).  &lt;li&gt;Manage Spam for questions &amp;amp; comments.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;The project should be written in C#, beyond that, feel free to use whatever technologies that you are most comfortable with.&lt;/p&gt; &lt;p&gt;Things that we will be looking at:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Code quality  &lt;li&gt;Architecture  &lt;li&gt;Ease of modification  &lt;li&gt;Efficiency of implementation  &lt;li&gt;Ease of setup &amp;amp; deployment&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Please send us the link to a Git repository containing the project, as well as any instructions that might be necessary.&lt;/p&gt; &lt;p&gt;Thanks in advance,&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Oren Eini&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This post will go live about two weeks after I started sending this to candidates, so I am not sure yet what the response would be.&lt;/p&gt;</description><link>http://ayende.com/blog/161026/hibernating-rhinos-practices-a-sample-project?key=36b548de-576b-479b-9eeb-9547a76aa1a3</link><guid>http://ayende.com/blog/161026/hibernating-rhinos-practices-a-sample-project?key=36b548de-576b-479b-9eeb-9547a76aa1a3</guid><pubDate>Fri, 22 Feb 2013 10:00:00 GMT</pubDate></item><item><title>Defensive coding is your friend</title><description>&lt;p&gt;We just had a failing test:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_thumb.png" width="843" height="65"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;As you can see we assumed that fiddler is running, when it isn’t. Here is the bug:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_thumb_1.png" width="733" height="244"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Now, this is great when I am testing things out, and want to check what is going on the wire using Fiddler, but I always have to remember to revert this change, otherwise we will have a failing test and a failing build.&lt;/p&gt; &lt;p&gt;That isn’t very friction free, so I added the following:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Defensive-coding-is-your-friend_B61B/image_thumb_2.png" width="578" height="212"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Now the code is smart enough to not fail the test if we didn’t do things right.&lt;/p&gt;</description><link>http://ayende.com/blog/160898/defensive-coding-is-your-friend?key=606f3fbb-4e29-4517-9cf6-3ed9befa2dc9</link><guid>http://ayende.com/blog/160898/defensive-coding-is-your-friend?key=606f3fbb-4e29-4517-9cf6-3ed9befa2dc9</guid><pubDate>Tue, 12 Feb 2013 10:00:00 GMT</pubDate></item><item><title>Hibernating Rhinos Practices: Pairing, testing and decision making</title><description>&lt;p&gt;We actually pair quite a lot, either physically (most of our stations have two keyboards &amp;amp; mice for that exact purpose) or remotely (Skype / Team Viewer).&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/pairing-testing-and-decision-making_C5A6/2013-01-27%2014.05.24%20HDR_2.jpg"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2013-01-27 14.05.24 HDR" border="0" alt="2013-01-27 14.05.24 HDR" src="http://ayende.com/blog/Images/Windows-Live-Writer/pairing-testing-and-decision-making_C5A6/2013-01-27%2014.05.24%20HDR_thumb.jpg" width="360" height="480"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And yet, I would say that for the vast majority of cases, we don’t pair. Pairing is usually called for when we need two pairs of eyes to look at a problem, for non trivial debugging and that is about it.&lt;/p&gt; &lt;p&gt;Testing is something that I deeply believe in, at the same time that I distrust unit testing. Most of our tests are actually system tests. That test the system end to end. Here is an example of such a test:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;[Fact]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CanProjectAndSort()
{
    &lt;span class="kwrd"&gt;using&lt;/span&gt;(var store = NewDocumentStore())
    {
        &lt;span class="kwrd"&gt;using&lt;/span&gt;(var session = store.OpenSession())
        {
            session.Store(&lt;span class="kwrd"&gt;new&lt;/span&gt; Account
            {
                Profile = &lt;span class="kwrd"&gt;new&lt;/span&gt; Profile
                {
                    FavoriteColor = &lt;span class="str"&gt;"Red"&lt;/span&gt;,
                    Name = &lt;span class="str"&gt;"Yo"&lt;/span&gt;
                }
            });
            session.SaveChanges();
        }
        &lt;span class="kwrd"&gt;using&lt;/span&gt;(var session = store.OpenSession())
        {
            var results = (from a &lt;span class="kwrd"&gt;in&lt;/span&gt; session.Query&amp;lt;Account&amp;gt;()
                           .Customize(x =&amp;gt; x.WaitForNonStaleResults())
                           orderby a.Profile.Name
                           select &lt;span class="kwrd"&gt;new&lt;/span&gt; {a.Id, a.Profile.Name, a.Profile.FavoriteColor}).ToArray();


            Assert.Equal(&lt;span class="str"&gt;"Red"&lt;/span&gt;, results[0].FavoriteColor);
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Most of our new features are usually built first, then get tests for them. Mostly because it is more efficient to get things done by experimenting a lot without having tests to tie you down.&lt;/p&gt;
&lt;p&gt;Decision making is something that I am trying to work on. For the most part, I have things that I feel very strongly about. Production worthiness is one such scenario, and I get annoyed if something is obviously stupid, but a lot of the time decisions can fall into the either or category, or are truly preferences issues. I still think that too much goes through me, including things that probably should not.&amp;nbsp; I am trying to encourage things so I wouldn’t be in the loop so much. We are making progress, but we aren’t there yet.&lt;/p&gt;
&lt;p&gt;Note that this post is mostly here to serve as a point of discussion. I am not really sure what to put in here, the practices we do are pretty natural, from my point of view. And I would appreciate any comments asking for clarifications.&lt;/p&gt;</description><link>http://ayende.com/blog/160902/hibernating-rhinos-practices-pairing-testing-and-decision-making?key=42eb0a9e-8481-4897-a1b5-13fbd2e09623</link><guid>http://ayende.com/blog/160902/hibernating-rhinos-practices-pairing-testing-and-decision-making?key=42eb0a9e-8481-4897-a1b5-13fbd2e09623</guid><pubDate>Tue, 05 Feb 2013 10:00:00 GMT</pubDate></item><item><title>Hibernating Rhinos Practices: We are hiring again</title><description>&lt;p&gt;As part of this series, I wanted to take the time and let you know that we are hiring full time developers again.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;strong&gt;This is applicable solely for developers in Israel&lt;/strong&gt;. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;We are working with C# (although I’ll admit that sometime we make it scream a little bit:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Hibernating-Rhinos-Practices-We-are-hiri_BF19/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Hibernating-Rhinos-Practices-We-are-hiri_BF19/image_thumb.png" width="289" height="278"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Candidate should be able to provide a project (and preferably more than one) that we can look at to see their code. It has got to be &lt;em&gt;your&lt;/em&gt; code. It is ain’t yours (if it is code that you wrote for an employer, or if it is a university code project) I &lt;em&gt;don’t wanna see it&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;We are talking about a full time employee position, working on RavenDB, Uber Profiler, RavenFS and a bunch of other stuff that I don’t want to talk about yet.&lt;/p&gt; &lt;p&gt;Ping me with your CV if you are interested.&lt;/p&gt;</description><link>http://ayende.com/blog/160901/hibernating-rhinos-practices-we-are-hiring-again?key=78f3e7b7-d7a5-4238-879f-33809dceb126</link><guid>http://ayende.com/blog/160901/hibernating-rhinos-practices-we-are-hiring-again?key=78f3e7b7-d7a5-4238-879f-33809dceb126</guid><pubDate>Mon, 04 Feb 2013 10:00:00 GMT</pubDate></item><item><title>Hibernating Rhinos Practices: Development Workflow</title><description>&lt;p&gt;The development workflow refers to how a developer decides what to do next, how tasks are organized, assigned and worked on.&lt;/p&gt; &lt;p&gt;Typically, we dedicate a lot of the Israeli’s team time to doing ongoing support and maintenance tasks. So a lot of the work are things that show up on the mailing lists. We usually triage them to one of four levels:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Interesting stuff that is outside of core competencies, or stuff that is nice to have that we don’t have resources for. We would usually handle that by requesting a pull request, or creating a low priority issue.&lt;/li&gt; &lt;li&gt;Feature requests / ideas – usually go to the issuer tracker and wait there until assigned / there is time to do them.&lt;/li&gt; &lt;li&gt;Bugs in our products – depending on severity, usually they are fixed on the spot, sometimes they are low priority and get to the issue tracker.&lt;/li&gt; &lt;li&gt;Priority Bugs – usually get to the top of the list over anything and everything else.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;It is obviously a bit more complex, because if we are working on a particular area already, we usually also take the time to cover the easy-to-do stuff from the issue tracker.&lt;/p&gt; &lt;p&gt;Important things:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;We generally don’t pay attention to releases, unless we have one pending for a product (for example, upcoming stable release for RavenDB).&lt;/li&gt; &lt;li&gt;We don’t usually try to prioritize issues. Most of them are just there, and get picked up by whoever gets them first.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;We following slightly different workflows for Uber Prof &amp;amp; RavenDB. With Uber Prof, every single push generate a client visible build, and we have auto update to make sure that most people run on the very latest.&lt;/p&gt; &lt;p&gt;With RavenDB, we have the unstable builds, which is what every single push translates to, and the stable builds, which have a much more involved release process.&lt;/p&gt; &lt;p&gt;We tend to emphasize getting things out the door over the Thirteen Steps to Properly Release Software.&lt;/p&gt; &lt;p&gt;An important rule of thumb, if you are still the office by 7 PM, you have &lt;em&gt;better&lt;/em&gt; showed up at 11 or so, just because zombies are cool nowadays doesn’t mean you have to be one. I am personally exempted from the rule, though.&lt;/p&gt; &lt;p&gt;Next, I’ll discuss pairing, testing and decision making.&lt;/p&gt;</description><link>http://ayende.com/blog/160900/hibernating-rhinos-practices-development-workflow?key=6d1c9165-1782-40d9-89ca-b09c4da5318a</link><guid>http://ayende.com/blog/160900/hibernating-rhinos-practices-development-workflow?key=6d1c9165-1782-40d9-89ca-b09c4da5318a</guid><pubDate>Thu, 31 Jan 2013 10:00:00 GMT</pubDate></item><item><title>Hibernating Rhinos Practices: Intro</title><description>&lt;p&gt;I was &lt;a href="http://ayende.com/blog/160706/design-patterns-in-the-test-of-time-iterator?key=6d22c7155f0d4cf29e6084648b24fb71"&gt;asked&lt;/a&gt; to comment a bit on our internal practices in Hibernating Rhinos. Before I can do that, I have to explain about how we are structured.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The development team in Israel compose the core of the company.&lt;/li&gt; &lt;li&gt;There are additional contractors that do work in Poland, the states and the UK. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;We rarely make distinctions between locations for work, although obviously we have specializations. &lt;a href="http://blog.functionalfun.net/"&gt;Samuel&lt;/a&gt; is our go to guy for “Make things pretty” and “Silverlight hairloss”, for example, Arek is the really good in pointing to the right direction when there is a problem, and so on.&lt;/p&gt; &lt;p&gt;We currently have the following projects in place:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;RavenDB&lt;/li&gt; &lt;li&gt;Uber Profiler&lt;/li&gt; &lt;li&gt;RavenFS&lt;/li&gt; &lt;li&gt;License / Orders Management&lt;/li&gt; &lt;li&gt;RavenDB.Net&lt;/li&gt; &lt;li&gt;HibernatingRhinos.com&lt;/li&gt; &lt;li&gt;ayende.com&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Note that this is probably a partial list. And you might have noticed that I also included internal stuff, because that is also work, and something that we do.&lt;/p&gt; &lt;p&gt;In general, there isn’t a lot of “you work on this, or you work on that”, although again, there are areas of specialization. Fitzchak has been doing a lot of the work on Uber Prof, and Daniel is spending a lot of time on the RavenDB Studio. That doesn’t mean that tomorrow you wouldn’t find Fitzchak hacking on RavenDB indexes or Pawel working on exporting the profiler data to excel, and so on.&lt;/p&gt; &lt;p&gt;Next, I’ll discuss how we deal with the development workflow.&lt;/p&gt;</description><link>http://ayende.com/blog/160899/hibernating-rhinos-practices-intro?key=c8f1ab21-1220-44c8-b516-665a90e6a3a3</link><guid>http://ayende.com/blog/160899/hibernating-rhinos-practices-intro?key=c8f1ab21-1220-44c8-b516-665a90e6a3a3</guid><pubDate>Wed, 30 Jan 2013 10:00:00 GMT</pubDate></item><item><title>Riddle me this, why won’t this code work?</title><description>&lt;p&gt;The following code will &lt;em&gt;not&lt;/em&gt; result in the expected output:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt;(var mem = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream())
{
    &lt;span class="kwrd"&gt;using&lt;/span&gt;(var gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(mem, CompressionMode.Compress, leaveOpen:&lt;span class="kwrd"&gt;true&lt;/span&gt;))
    {
        gzip.WriteByte(1);
        gzip.WriteByte(2);
        gzip.WriteByte(1);
        gzip.Flush();
    }
    
    &lt;span class="kwrd"&gt;using&lt;/span&gt; (var gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(mem, CompressionMode.Compress, leaveOpen: &lt;span class="kwrd"&gt;true&lt;/span&gt;))
    {
        gzip.WriteByte(2);
        gzip.WriteByte(1);
        gzip.WriteByte(2);
        gzip.Flush();
    }

    mem.Position = 0;

    &lt;span class="kwrd"&gt;using&lt;/span&gt; (var gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(mem, CompressionMode.Decompress, leaveOpen: &lt;span class="kwrd"&gt;true&lt;/span&gt;))
    {
        Console.WriteLine(gzip.ReadByte());
        Console.WriteLine(gzip.ReadByte());
        Console.WriteLine(gzip.ReadByte());
    }


    &lt;span class="kwrd"&gt;using&lt;/span&gt; (var gzip = &lt;span class="kwrd"&gt;new&lt;/span&gt; GZipStream(mem, CompressionMode.Decompress, leaveOpen: &lt;span class="kwrd"&gt;true&lt;/span&gt;))
    {
        Console.WriteLine(gzip.ReadByte());
        Console.WriteLine(gzip.ReadByte());
        Console.WriteLine(gzip.ReadByte());
    }
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why? And what can be done to solve this?&lt;/p&gt;</description><link>http://ayende.com/blog/160481/riddle-me-this-why-wont-this-code-work?key=b7ffffb2-fcd8-4efd-b6b5-d63c9f5d62fc</link><guid>http://ayende.com/blog/160481/riddle-me-this-why-wont-this-code-work?key=b7ffffb2-fcd8-4efd-b6b5-d63c9f5d62fc</guid><pubDate>Thu, 27 Dec 2012 10:00:00 GMT</pubDate></item><item><title>Tooling shout out: .NET Memory Profiler</title><description>&lt;p&gt;&lt;a href="http://memprofiler.com/"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Tool-shoutout-.NET-Memory-Profiler_4F11/image_3.png" width="404" height="86"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;To start with, I don’t have any association with them, I got nothing (no money, free license, promise of goodwill or anything else at all) from the SciTech Software (the creators of &lt;a href="http://memprofiler.com"&gt;.NET Memory Profiler.&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://memprofiler.com"&gt;This tool&lt;/a&gt; has been &lt;em&gt;instrumental&lt;/em&gt; in figuring out our recent memory issues. I have tried dotTrace Memory, JustTrace and WinDBG, but this tool outshone them all and was able to point us quite quickly to the root cause that we had to deal with, and from there, it was quite easy to reach a solution.&lt;/p&gt; &lt;p&gt;Highly recommended.&lt;/p&gt;</description><link>http://ayende.com/blog/160449/tooling-shout-out-net-memory-profiler?key=bd75f634-5b49-4318-9644-d1b86c672dd7</link><guid>http://ayende.com/blog/160449/tooling-shout-out-net-memory-profiler?key=bd75f634-5b49-4318-9644-d1b86c672dd7</guid><pubDate>Tue, 25 Dec 2012 10:00:00 GMT</pubDate></item><item><title>Implementing LRU cache</title><description>&lt;p&gt;In my last post I mentioned that checking whatever a user is an administrator or not using Active Directory query can be &lt;em&gt;slow&lt;/em&gt;. That means that we can just make use of that, we have to cache that.&lt;/p&gt; &lt;p&gt;When caching is involved, we have to consider a few things. When do we expire the data? How much memory are we going to use? How do we handle concurrency?&lt;/p&gt; &lt;p&gt;The first thing that pops to mind is the usage of MemoryCache, now part of the .NET framework and easily accessible. Sadly, this is a &lt;em&gt;heavy&lt;/em&gt; weight object, it creates its own threads to manage its state, which probably means we don’t want to use it for a fairly simple feature like this.&lt;/p&gt; &lt;p&gt;Instead, I implemented the following:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CachingAdminFinder
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CachedResult
    {
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Usage;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime Timestamp;
        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; Value;
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; CacheMaxSize = 25;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; TimeSpan MaxDuration = TimeSpan.FromMinutes(15);
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; ConcurrentDictionary&amp;lt;SecurityIdentifier, CachedResult&amp;gt; cache =
        &lt;span class="kwrd"&gt;new&lt;/span&gt; ConcurrentDictionary&amp;lt;SecurityIdentifier, CachedResult&amp;gt;();


    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsAdministrator(WindowsIdentity windowsIdentity)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (windowsIdentity == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentNullException(&lt;span class="str"&gt;"windowsIdentity"&lt;/span&gt;);
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (windowsIdentity.User == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; ArgumentException(&lt;span class="str"&gt;"Could not find user on the windowsIdentity"&lt;/span&gt;, &lt;span class="str"&gt;"windowsIdentity"&lt;/span&gt;);

        CachedResult &lt;span class="kwrd"&gt;value&lt;/span&gt;;
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (cache.TryGetValue(windowsIdentity.User, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;) &amp;amp;&amp;amp; (DateTime.UtcNow - &lt;span class="kwrd"&gt;value&lt;/span&gt;.Timestamp) &amp;lt;= MaxDuration)
        {
            Interlocked.Increment(&lt;span class="kwrd"&gt;ref&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;.Usage);
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;.Value;
        }
        &lt;span class="kwrd"&gt;bool&lt;/span&gt; isAdministratorNoCache;
        &lt;span class="kwrd"&gt;try&lt;/span&gt;
        {
            isAdministratorNoCache = IsAdministratorNoCache(windowsIdentity.Name);
        }
        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (Exception e)
        {
            log.WarnException(&lt;span class="str"&gt;"Could not determine whatever user is admin or not, assuming not"&lt;/span&gt;, e);
            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
        }
        var cachedResult = &lt;span class="kwrd"&gt;new&lt;/span&gt; CachedResult
            {
                Usage = &lt;span class="kwrd"&gt;value&lt;/span&gt; == &lt;span class="kwrd"&gt;null&lt;/span&gt; ? 1 : &lt;span class="kwrd"&gt;value&lt;/span&gt;.Usage + 1,
                Value = isAdministratorNoCache,
                Timestamp = DateTime.UtcNow
            };

        cache.AddOrUpdate(windowsIdentity.User, cachedResult, (_, __) =&amp;gt; cachedResult);
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (cache.Count &amp;gt; CacheMaxSize)
        {
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var source &lt;span class="kwrd"&gt;in&lt;/span&gt; cache
                .OrderByDescending(x =&amp;gt; x.Value.Usage)
                .ThenBy(x =&amp;gt; x.Value.Timestamp)
                .Skip(CacheMaxSize))
            {
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (source.Key == windowsIdentity.User)
                    &lt;span class="kwrd"&gt;continue&lt;/span&gt;; &lt;span class="rem"&gt;// we don't want to remove the one we just added&lt;/span&gt;
                CachedResult ignored;
                cache.TryRemove(source.Key, &lt;span class="kwrd"&gt;out&lt;/span&gt; ignored);
            }
        }

        &lt;span class="kwrd"&gt;return&lt;/span&gt; isAdministratorNoCache;
    }

    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsAdministratorNoCache(&lt;span class="kwrd"&gt;string&lt;/span&gt; username)
    {
       &lt;span class="rem"&gt;// see previous post&lt;/span&gt;
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Amusingly enough, properly handling the cache takes (much) more code than it takes to actually get the value.&lt;/p&gt;
&lt;p&gt;We use ConcurrentDictionary as the backing store for our cache, and we enhance the value with usage &amp;amp; timestamp information. Those come in handy when the cache grows too big and need to be trimmed. &lt;/p&gt;
&lt;p&gt;Note that we also make sure to check the source every 15 minutes or so, because there is nothing as annoying as “you have to restart the server for it to pick the change”. We also handle the case were we &lt;em&gt;can’t&lt;/em&gt; get this information for some reason.&lt;/p&gt;
&lt;p&gt;In practice, I doubt that we will ever hit the cache max size limit, but I wouldn’t have been able to live with myself without adding the check &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://ayende.com/blog/Images/Windows-Live-Writer/Implementing-LRU-cache_B18C/wlEmoticon-smile_2.png"&gt;.&lt;/p&gt;</description><link>http://ayende.com/blog/158433/implementing-lru-cache?key=03f711ec-a961-4db9-bfc0-30af0e95138f</link><guid>http://ayende.com/blog/158433/implementing-lru-cache?key=03f711ec-a961-4db9-bfc0-30af0e95138f</guid><pubDate>Thu, 13 Sep 2012 09:00:00 GMT</pubDate></item><item><title>Are you an administrator?</title><description>&lt;p&gt;In RavenDB vNext, we tightened the security story a bit. Some operations that used to be possible for standard users are now administrator operations. For example, creating a new database require you to be admin.&lt;/p&gt; &lt;p&gt;Figuring out whatever you are admin is a bit tough, though. In particular, we use the following logic to determine that:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;If you logged in using OAuth, the credentials will tell us whatever you are admin or not.&lt;/li&gt; &lt;li&gt;If you are logged in using Windows Auth, we make the following assumption:&lt;/li&gt; &lt;ul&gt; &lt;li&gt;If you are a Windows Admin, you are an administrator (&lt;strong&gt;ouch!&lt;/strong&gt;).&lt;/li&gt; &lt;li&gt;If you are running on the same user as the one RavenDB is using, you are an administrator (debug / dev scenarios).&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;If you are running embedded, you are admin.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;You might have noticed that there is an “ouch” on the Windows Admin line. The reason for that is that it is actually quite hard to figure that one out. RavenDB is running as a web server, and when we use Windows Auth, we get a WindowsIdentity that we can use. The problem is with UAC. When that is turned on, what we get is the &lt;em&gt;non elevated user. &lt;/em&gt;But that user is &lt;em&gt;not&lt;/em&gt; an Admin in the Windows sense of the word. We don’t actually care about that (it isn’t like we need to impersonate the user), we just use that as a “yes/no” for certain ops.&lt;/p&gt; &lt;p&gt;This is documented here: &lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/679546/problem-with-windowsprincipal-isinrole-when-uac-is-enabled"&gt;https://connect.microsoft.com/VisualStudio/feedback/details/679546/problem-with-windowsprincipal-isinrole-when-uac-is-enabled&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The resolution is by design. &lt;/p&gt; &lt;p&gt;So… we need another way to check for this. Luckily, since we don’t need impersonation, we can just check Active Directory for that. Here is how we do so:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsAdministratorNoCache(&lt;span class="kwrd"&gt;string&lt;/span&gt; username)
{
    PrincipalContext ctx;
    &lt;span class="kwrd"&gt;try&lt;/span&gt;
    {
        Domain.GetComputerDomain();
        &lt;span class="kwrd"&gt;try&lt;/span&gt;
        {
            ctx = &lt;span class="kwrd"&gt;new&lt;/span&gt; PrincipalContext(ContextType.Domain);
        }
        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (PrincipalServerDownException)
        {
            &lt;span class="rem"&gt;// can't access domain, check local machine instead &lt;/span&gt;
            ctx = &lt;span class="kwrd"&gt;new&lt;/span&gt; PrincipalContext(ContextType.Machine);
        }
    }
    &lt;span class="kwrd"&gt;catch&lt;/span&gt; (ActiveDirectoryObjectNotFoundException)
    {
        &lt;span class="rem"&gt;// not in a domain&lt;/span&gt;
        ctx = &lt;span class="kwrd"&gt;new&lt;/span&gt; PrincipalContext(ContextType.Machine);
    }
    var up = UserPrincipal.FindByIdentity(ctx, username);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (up != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
        PrincipalSearchResult&amp;lt;Principal&amp;gt; authGroups = up.GetAuthorizationGroups();
        &lt;span class="kwrd"&gt;return&lt;/span&gt; authGroups.Any(principal =&amp;gt;
                              principal.Sid.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) ||
                              principal.Sid.IsWellKnown(WellKnownSidType.AccountDomainAdminsSid) ||
                              principal.Sid.IsWellKnown(WellKnownSidType.AccountAdministratorSid) ||
                              principal.Sid.IsWellKnown(WellKnownSidType.AccountEnterpriseAdminsSid));
    }
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here we check whatever the user is directly or indirectly and admin. Note that we have to take care of cases in which we are running inside &amp;amp; outside a domain, as well as cases where the domain controller is down.&lt;/p&gt;
&lt;p align="left"&gt;This works, but there is just one problem with that, it is &lt;em&gt;sloooow.&lt;/em&gt; As in, multiple seconds slow. Even on the local machine without any domain involved.&lt;/p&gt;
&lt;p align="left"&gt;I’ll discuss how we solved that on my next post.&lt;/p&gt;</description><link>http://ayende.com/blog/158401/are-you-an-administrator?key=6138b555-bbd5-4bd8-9a7e-9a8af5fbf512</link><guid>http://ayende.com/blog/158401/are-you-an-administrator?key=6138b555-bbd5-4bd8-9a7e-9a8af5fbf512</guid><pubDate>Wed, 12 Sep 2012 09:00:00 GMT</pubDate></item><item><title>OH: This is beautiful</title><description>&lt;p&gt;I just said that when I got this on the debugger:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/OH-This-is-beautiful_13BE0/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/OH-This-is-beautiful_13BE0/image_thumb.png" width="447" height="668"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I think that I need to get off the computer, and I’ll do so, just as soon as I am done with this feature.&lt;/p&gt;</description><link>http://ayende.com/blog/157409/oh-this-is-beautiful?key=9a43d645-cb3e-49d9-8686-9f76d5ee2349</link><guid>http://ayende.com/blog/157409/oh-this-is-beautiful?key=9a43d645-cb3e-49d9-8686-9f76d5ee2349</guid><pubDate>Fri, 10 Aug 2012 09:00:00 GMT</pubDate></item><item><title>I hate Hello World questions</title><description>&lt;p&gt;That is what I call things like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/I-hate-Hello-World-questions_83B6/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/I-hate-Hello-World-questions_83B6/image_thumb.png" width="503" height="84"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It was part of a question I was asked, and the question contained things like:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;I've a field (Field2) in MyClass as nested Dictionary and i have an index for Field 1.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;There are several issues with this style of question:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;It make it harder to answer, because you have to keep a mapping of that in your head.&lt;/li&gt; &lt;li&gt;There is no meaning to the question, we can’t figure out whatever this is a good or bad scenario.&lt;/li&gt; &lt;li&gt;Usually the problem description contains references to the real model, which I haven’t seen and don’t know anything about.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Annoying.&lt;/p&gt;</description><link>http://ayende.com/blog/157537/i-hate-hello-world-questions?key=fc59b8f2-fdc2-41f3-b51b-04884d38e97d</link><guid>http://ayende.com/blog/157537/i-hate-hello-world-questions?key=fc59b8f2-fdc2-41f3-b51b-04884d38e97d</guid><pubDate>Thu, 09 Aug 2012 09:00:00 GMT</pubDate></item><item><title>It uses async, run for the hills (On .Net 4.0)</title><description>&lt;p&gt;One of the major problems in .NET 4.0 async operation stuff is the fact that an unobserved exception will ruthlessly kill your application.&lt;/p&gt; &lt;p&gt;Let us look at an example:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/It-uses-async-run-for-the-hills_AAFF/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/It-uses-async-run-for-the-hills_AAFF/image_thumb.png" width="300" height="139"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;On startup, check the server for any updates, without slowing down my system startup time. All well and good, as long as that server is reachable.&lt;/p&gt; &lt;p&gt;When it doesn’t, it will throw an exception, but not on the current thread, it will be thrown on another thread, and when the task is finalized, it will raise an UnobservedTaskException. Okay, so I’ll fix that and write code like this:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;CheckForUpdatesAsync().ContinueWith(task=&amp;gt; GC.KeepAlive(task.Exception));&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;And that would almost work, except the implementation of CheckForUpdateAsync is:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Task CheckForUpdatesAsync()
{
    var webRequest = WebRequest.Create(&lt;span class="str"&gt;"http://myserver.com/update-check"&lt;/span&gt;);
    webRequest.Method = &lt;span class="str"&gt;"POST"&lt;/span&gt;;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; webRequest.GetRequestStreamAsync()
        .ContinueWith(task =&amp;gt; task.Result.WriteAsync(CurrentVersion))
        &lt;font style="background-color: #ffff00"&gt;.ContinueWith(task =&amp;gt; webRequest.GetResponseAsync())&lt;/font&gt;
        .ContinueWith(task =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamReader(task.Result.GetResponseStream()).ReadToEnd())
        .ContinueWith(task =&amp;gt;
                          {
                              &lt;span class="kwrd"&gt;if&lt;/span&gt; (task.Result != &lt;span class="str"&gt;"UpToDate"&lt;/span&gt;)
                                  ShowUpdateDialogToUser();
                          });
}
&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Note the highlighted line, where we are essentially ignoring the failure to write to the server. &lt;em&gt;That&lt;/em&gt; task is going to go away unobserved, the result, when GC happens, you’ll have an unobserved task exception.&lt;/p&gt;
&lt;p&gt;This sort of error has all of the fun aspects of a good problem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only happen during errors&lt;/li&gt;
&lt;li&gt;Async in nature&lt;/li&gt;
&lt;li&gt;Bring down your application&lt;/li&gt;
&lt;li&gt;Error location and error notification are completely divorced from one another&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;It is actually worse than having a memory leak!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx"&gt;This post&lt;/a&gt; explains some of the changes made with regards to unobserved exceptions in 4.5, and I wholeheartedly support this, but in 4.0, writing code that uses the TPL is easy and fun, but require careful code review to make sure that you aren’t leaking an unobserved exception.&lt;/p&gt;</description><link>http://ayende.com/blog/157154/it-uses-async-run-for-the-hills-on-net-4-0?key=7cfced7d-d349-4051-aad0-05c705efe5cd</link><guid>http://ayende.com/blog/157154/it-uses-async-run-for-the-hills-on-net-4-0?key=7cfced7d-d349-4051-aad0-05c705efe5cd</guid><pubDate>Mon, 23 Jul 2012 09:00:00 GMT</pubDate></item><item><title>Why I LOVE ReSharper</title><description>&lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/5c1d04fe6126_10BAF/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/5c1d04fe6126_10BAF/image_thumb.png" width="430" height="142"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I mean, just look at this. This is magic.&lt;/p&gt; &lt;p&gt;More to the point, think about what this means to try to implement something like that. I wouldn’t know where to even start.&lt;/p&gt;</description><link>http://ayende.com/blog/153633/why-i-love-resharper?key=f502e4ed-41d1-4e0a-bf01-b7a1eaeedb98</link><guid>http://ayende.com/blog/153633/why-i-love-resharper?key=f502e4ed-41d1-4e0a-bf01-b7a1eaeedb98</guid><pubDate>Fri, 08 Jun 2012 09:00:00 GMT</pubDate></item><item><title>Truth in advertising</title><description>&lt;p&gt;So I am at a client site discussing things about their new version of the software. And while it is easy to promise things, we did a POC to make sure that things will work out.&lt;/p&gt; &lt;p&gt;Because I know users, I made sure to have this ready:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Truth-in-advertising_D6DB/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Truth-in-advertising_D6DB/image_thumb.png" width="805" height="172"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I do software behavior, but I know my limitations, and doing good looking UI is one of them.&lt;/p&gt; &lt;p&gt;I had too many software demos blow up because of silly UI issues. &lt;/p&gt;</description><link>http://ayende.com/blog/153089/truth-in-advertising?key=9006da2c-7c9f-4201-9919-984e1878f688</link><guid>http://ayende.com/blog/153089/truth-in-advertising?key=9006da2c-7c9f-4201-9919-984e1878f688</guid><pubDate>Wed, 06 Jun 2012 09:00:00 GMT</pubDate></item><item><title>When using the Task Parallel Library, Wait() is a BAD warning sign</title><description>&lt;p&gt;Take a look at the following code:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Task ParseAsync(IPartialDataAccess source, IPartialDataAccess seed, Stream output, IEnumerable&amp;lt;RdcNeed&amp;gt; needList)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Task.Factory.StartNew(() =&amp;gt;
    {
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var item &lt;span class="kwrd"&gt;in&lt;/span&gt; needList)
        {
            &lt;span class="kwrd"&gt;switch&lt;/span&gt; (item.BlockType)
            {
                &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Source:
                    source.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength)).Wait();
                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;
                &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Seed:
                    seed.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength)).Wait();
                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;
                &lt;span class="kwrd"&gt;default&lt;/span&gt;:
                    &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotSupportedException();
            }
        }
    });
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Do you see the problem in here?&lt;/p&gt;
&lt;p&gt;It is a result of a code review comment about improper use of async in a project. This resulted in a lot of Task showing up in the return methods, but not in any measurable improvement in the actual codebase use of asynchronicity.&lt;/p&gt;
&lt;p&gt;The problem is that when you need to work with such things in C# 4.0, you have to do some annoying things to get the code to work properly. In particular, this method was modified to be:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Task ParseAsync(IPartialDataAccess source, IPartialDataAccess seed, Stream output, IList&amp;lt;RdcNeed&amp;gt; needList, &lt;span class="kwrd"&gt;int&lt;/span&gt; position = 0)
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt;(position&amp;gt;= needList.Count)
  {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; CompletedTask();
  }
  var item = needList[position];
  Task task;
            
  &lt;span class="kwrd"&gt;switch&lt;/span&gt; (item.BlockType)
  {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Source:
            task = source.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength));
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Seed:
            task = seed.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength));
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        &lt;span class="kwrd"&gt;default&lt;/span&gt;:
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotSupportedException();
  }

  &lt;span class="kwrd"&gt;return&lt;/span&gt; task.ContinueWith(resultTask =&amp;gt;
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (resultTask.Status == TaskStatus.Faulted)
            resultTask.Wait(); &lt;span class="rem"&gt;// throws&lt;/span&gt;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ParseAsync(source, seed, output, needList, position + 1);
    }).Unwrap();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;This code is more complex, but it is actually making proper use of the TPL. We have changed the loop into a recursive function, so we can take advantage of ContinueWith to the next iteration of the loop.&lt;/p&gt;
&lt;p&gt;And no, I can’t &lt;em&gt;wait&lt;/em&gt; to get to C# 5.0 and have proper await work.&lt;/p&gt;</description><link>http://ayende.com/blog/155585/when-using-the-task-parallel-library-wait-is-a-bad-warning-sign?key=08f9a2f5-c34a-4961-8c19-e5782bcc39a1</link><guid>http://ayende.com/blog/155585/when-using-the-task-parallel-library-wait-is-a-bad-warning-sign?key=08f9a2f5-c34a-4961-8c19-e5782bcc39a1</guid><pubDate>Thu, 17 May 2012 09:00:00 GMT</pubDate></item><item><title>Security decisions: Separate Operations &amp; Queries</title><description>&lt;p&gt;The question came up several times in the mailing list with regards to how the RavenDB Authorization Bundle operates, and I think it serves a broader discussion.&lt;/p&gt; &lt;p&gt;Let us imagine a system where we have contracts, which may be in several states: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Mine – Contracts that an employee signed.  &lt;li&gt;Done – Standard users can view, Lawyers assigned to the company can sign.  &lt;li&gt;Draft – Lawyers can view / edit, Partners can approve.  &lt;li&gt;Proposed – Lawyers can create / edit, but only the lawyer that created it can view it, Partners can accept.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So far, fairly simple, right? Except the pure &lt;em&gt;hell&lt;/em&gt; that you are going to get into when you are trying to show the users all of the contracts that they can see, sorted by edit date and in the NDA category.&lt;/p&gt; &lt;p&gt;Why am I being so negative here? Well, let us look at what we are going to have to do in the most trivial of cases:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_thumb_1.png" width="450" height="221"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this sort of system, we are going to have to show the user all of the contracts that they are allowed to see, and show them some indication what operations they can do on each.&lt;/p&gt; &lt;p&gt;The problem is that generating this sort of view is &lt;em&gt;expensive&lt;/em&gt;. Especially when you have large amount of data to work through. More interesting, from a UX perspective, it also doesn’t really work that well. Most users would want a better separation of the things that they can do, probably something like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_9.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_thumb_3.png" width="450" height="221"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This allows us to do a first level filtering on the data itself, rather than try to apply security rules to it.&lt;/p&gt; &lt;p&gt;In the first case, we need to get all the contracts that we are allowed to see. The security rules above are &lt;em&gt;really&lt;/em&gt; simple, mind. But trying to translate them into an efficient query is going to be pretty hard. Both in terms of the code requires and the cost to actually perform the query on the server. There are other things that are involved as well, such as paging and sorting in such an environment.&amp;nbsp; I have created several such systems in the past, Rhino Security is probably the most well known of them, and it gets really hard to optimize things and make sure that everything works when you start getting more complex security rules (especially when you have a user editable security system, which is a common request).&lt;/p&gt; &lt;p&gt;The second case is cheaper because we can limit the choices that we see in the query itself. We may still need to apply security concerns, but those goes through the query directly, rather than a security sub system. This kind of change usually force people to be more explicit in what they want, and it result in a system that tends to be simpler. The security rules aren’t just something arbitrary that can be defined, they are actually visible on the screen (My Contracts, Drafts, etc). Changing them isn’t something that is done on an administrator’s whim.&lt;/p&gt; &lt;p&gt;Yes, this is a way to manage the client and their expectations, but that is &lt;em&gt;important&lt;/em&gt;. But what about the complex security that they want? &lt;/p&gt; &lt;p&gt;That might still be there, certainly, but that would be active mostly for operations (stuff that happen on a single entity), not on things that happen over all entities. It is drastically easier to make a single entity security decisions work efficiently than make it work over the whole set inside the database.&lt;/p&gt;</description><link>http://ayende.com/blog/152929/security-decisions-separate-operations-queries?key=dd5d38bf-cf0b-4233-b6c5-b75582e2e82f</link><guid>http://ayende.com/blog/152929/security-decisions-separate-operations-queries?key=dd5d38bf-cf0b-4233-b6c5-b75582e2e82f</guid><pubDate>Tue, 10 Apr 2012 10:00:00 GMT</pubDate></item><item><title>Hiding values, API keys and other fun stuff</title><description>&lt;p&gt;This post is mostly about fun ideas. In one scenario, we had the need to show data to the user, but there was some concern with regards to the hackability of the URL.&lt;/p&gt; &lt;p&gt;In general, you should be handle such things within your code, checking permissions, etc. But I decided to see if I can do something nice with things, and I got this:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; HideValues(&lt;span class="kwrd"&gt;string&lt;/span&gt; entityId, &lt;span class="kwrd"&gt;string&lt;/span&gt; tenantId, &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] key, &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] iv)
{
    &lt;span class="kwrd"&gt;using&lt;/span&gt; (var rijndael = Rijndael.Create())
    {
        rijndael.Key = key;
        rijndael.IV = iv;
        var memoryStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream();
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (var cryptoStream = &lt;span class="kwrd"&gt;new&lt;/span&gt; CryptoStream(memoryStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (var binaryWriter = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryWriter(cryptoStream))
        {
            binaryWriter.Write(entityId);
            binaryWriter.Write(tenantId);
            binaryWriter.Flush();

            cryptoStream.Flush();
        }
        var bytes = memoryStream.ToArray();
        var sb = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder();
        &lt;span class="kwrd"&gt;for&lt;/span&gt; (&lt;span class="kwrd"&gt;int&lt;/span&gt; index = 0; index &amp;lt; bytes.Length; index++)
        {
            var b = bytes[index];
            sb.Append(b.ToString(&lt;span class="str"&gt;"X"&lt;/span&gt;));
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (index % (bytes.Length/4) == 0 &amp;amp;&amp;amp; index &amp;gt; 0)
                sb.Append(&lt;span class="str"&gt;'-'&lt;/span&gt;);
        }
        &lt;span class="kwrd"&gt;return&lt;/span&gt; sb;
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;This will generate a “guid looking” value that we can send to the user. When they send it back to us, we can decrypt it and figure out what is actually going on in there.&lt;/p&gt;
&lt;p&gt;Because it is encrypted, we know that this is a valid key, because otherwise we wouldn’t be able to decrypt it to valid data.&lt;/p&gt;
&lt;p&gt;Passing 15 and 32 as the first two values, I got the following value back: 2A8AC8888-46B92092-BFD81393-7A6FB1&lt;/p&gt;
&lt;p&gt;And it handle larger values as easily, of course. Quite fun, even if I say so myself. Not sure if this is &lt;em&gt;useful&lt;/em&gt;, but I got into writing code because it is a great hobby.&lt;/p&gt;</description><link>http://ayende.com/blog/153345/hiding-values-api-keys-and-other-fun-stuff?key=280b7c8b-e590-4671-8c69-ef25955eaa3f</link><guid>http://ayende.com/blog/153345/hiding-values-api-keys-and-other-fun-stuff?key=280b7c8b-e590-4671-8c69-ef25955eaa3f</guid><pubDate>Mon, 09 Apr 2012 10:00:00 GMT</pubDate></item><item><title>The economics of continuous deployment</title><description>&lt;p&gt;
	One of the things that I did, almost by accident, when we started Hibernating Rhinos was to create a CI server and a public daily build server. And every single successful build ended up in customer hands. That was awesome in many respects, it removed a lot of the &amp;ldquo;we have got to make a new release&amp;rdquo; pressure, because we were making new releases, sometimes multiple times a day.&lt;/p&gt;
&lt;p&gt;
	When we started with RavenDB, it was obvious to me that this was what we were going to do with it as well, because the advantages to this approach as so clear. With RavenDB, we needed a two stage system, but still, every single build gets to the customer hands.&lt;/p&gt;
&lt;p&gt;
	Awesome, great, outstanding, exceptional and other such synonyms. As long as you look at this from one angle, the one in which we are only concerned about the technical challenges of delivering software .The problem is that there are additional things to note here. Economic challenges.&lt;/p&gt;
&lt;p&gt;
	Let us take the profiler as a good example. It was released in beta on the Jan 1, 2009, and since then we had 920 separate builds, adding a &lt;em&gt;ton &lt;/em&gt;of new features, capabilities, improving performance, making things smoother and in general making it a better product.&lt;/p&gt;
&lt;p&gt;
	That is over &lt;em&gt;3 years&lt;/em&gt; without a major release, mostly because we never had the need to do this, we kept delivering software on a day to day basis.&lt;/p&gt;
&lt;p&gt;
	During that time, we delivered features such as viewing the result set, checking the query plan of a query (in all major databases), exporting the entire session to HTML so you can send it to your DBA, CI integration and &lt;em&gt;so much more&lt;/em&gt;. It has been wonderful.&lt;/p&gt;
&lt;p&gt;
	Except&amp;hellip; this has one implications that I didn&amp;rsquo;t think of at the time. If you bought NH Prof on the 1st Jan, 2009 you got 3 years of product updates, for no additional costs. And unless we create a new major version, you can keep using the software, including all the updates and improvements, without paying.&lt;/p&gt;
&lt;p&gt;
	That is great for the very early customers, but not so good for the people who need to eat so they can work on the profiler. Let us think about the implications of this a bit more, okay?&lt;/p&gt;
&lt;p&gt;
	In order for us to actually make money, we have to:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		keep expanding our one-off customer base, which is going to hit a limit at some point.&lt;/li&gt;
	&lt;li&gt;
		create a new version, getting the old customer to purchase the updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	Seems simple, right? This is what most companies do, and how most software is sold. You get a license for version 1 and you buy a license for version 2.&lt;/p&gt;
&lt;p&gt;
	So far, so good. But let us consider the implications of that. In order to get the old users to buy the new one, I have to put some really nice stuff in the next version. Which means that I have to do a lot of &amp;ldquo;secret&amp;rdquo; development because I can&amp;rsquo;t just release it on our usual continuous deployment mode. That sucks. And it also means that features that are already coded are actually disabled because we defer them to the next version.&lt;/p&gt;
&lt;p&gt;
	So, the next version of the profilers is going to have to have some interesting features to get people to buy it. One of them is production profiling. It has actually been around for quite a while. It has simply been #ifdef&amp;rsquo;ed out of the product, because it is something that we keep for the next version.&lt;/p&gt;
&lt;p&gt;
	I just checked, and I was acutely surprised by what I found. The initial work for production profiling was done in Jan 2010, it is &lt;em&gt;working &lt;/em&gt;since then. I got side tracked with RavenDB so I never had the chance to actually complete the rest of the features for 2.x and release them all.&lt;/p&gt;
&lt;p&gt;
	In mid 2010 we started experimenting with subscriptions. Instead of having a one time payment model, we moved to a pay as you go. So as long as you were using the profiler, you were paying for it, and in return, we provided all of those new features.&lt;/p&gt;
&lt;p&gt;
	I have been thinking about this a lot lately. I strongly lean toward making the next version of the profiler (coming soon, and it will have a &lt;em&gt;bunch&lt;/em&gt; of nice features) subscription only.&lt;/p&gt;
&lt;p&gt;
	My current thinking it to allow two modes of buying the product. Monthly / yearly subscription and a one time fee that give you 18 months of usage (and doesn&amp;rsquo;t re-charge). That would allow us to keep producing software in incremental steps, without having to go away for a while and work in secret on big ticket features just so we can have enough stuff to put on &amp;ldquo;why you should buy 2.x&amp;rdquo; list.&lt;/p&gt;
&lt;p&gt;
	I would appreciate any feedback that you may have.&lt;/p&gt;
</description><link>http://ayende.com/blog/154689/the-economics-of-continuous-deployment?key=d1efe164-c458-461b-a2c7-def34546a071</link><guid>http://ayende.com/blog/154689/the-economics-of-continuous-deployment?key=d1efe164-c458-461b-a2c7-def34546a071</guid><pubDate>Fri, 10 Feb 2012 14:51:34 GMT</pubDate></item></channel></rss>