Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,524
|
Comments: 51,159
Privacy Policy · Terms
filter by tags archive
time to read 4 min | 702 words

Lame title, but bear with me.

I have got a set of XML files that conform to an XSD schema, specifically, this one. I want to add additional elements and attributes to the documents, without breaking the schema, and hopefully without changing the code that read the schema.

Basically, I have this:

<class name="Blog" table="Blogs">

       <search:indexed-entity index="indexes/blogs"/>

       <property name="Subtitle">

              <search:field index="tokenized"/>

       </property>

</class>

I have bolded the parts that I want to add to the document. Any suggestions?

time to read 12 min | 2250 words

Tomer Gabel commented on my post about debuggable configuration:

This may be debuggable, but it sure as hell doesn't look like configuration to me. Configuration should be declarative and should not contain complex logic (what you show above definitely falls under that category in my book). This sort of script is, as far as I'm concerned, tantamount to collating all your configurable properties into one external, dynamically-compiled class -- in other words, hardcoded.

Let me just point out what I tried to do when I started using this approach:

death.by.xml.png

Looks familiar, anyone? I have shown this image to a fair amount of people, I got a lot of guilty looks :-) and general acknowledgement that this is a very bad place to be.

Now, to Tomer's comment:

This is a dynamically compiled class, but I wouldn't call it hard coded. It has all the features of a configuration file, i.e: restart the app and it will get the chances, I even has an app when I can do this type of changes on the fly. Declarative is an issue because you start to get out of control very fast with it in even mildly complex scenarios.

When I need to change a property or a feature, I can do so by opening this in notepad, make a change, and continue, there is nothing else that is needed to happen. I routinely does such things on production (tuning parameters, etc). I believe that this approach is far more common in dynamic langauges. Configuring MediaWiki, for instnace, is done by editing a php file.

This simplify things to a large degree, no need to extract values form XML, build the object graph, transform it, etc. I can just build the final result directly. The code I have shown is also doing some glue to connect some parts of the application. I mentioned that I am not sure if it is the responsability of the configuration to do so, but that is another matter.

Where does XML configuration fails?

Repeated configuration, I need to define 10 things of the same kind, with slight variations. For instance, defining a customer, where each customer has a different connection string:

customersDatabases = {

      "Northwind"       : "Data Source=...",

      "AdventureWorks"  : "Data Source=..."

      }

     

for entry in customersDatabases:

      Application.RegisterClientDatabase(entry.Key, entry.Value, ClientOptions.UseSharedConfiguration)

Now, imagine trying to do that in XML. Specifying debug/release configuration is also much easier:

if Environment.MachineName ~= /prod/: #production

      Application.LogLevel = LogLevel.Error

      Application.CrashReport = ( EmailReport("admin@site.com"), SmsReport("132432142") )

      Application.ShowErrorToUser = false

     

if Environment.MachineName ~= /test/: # test / staging

      Application.LogLevel = LogLevel.Info

      Application.CrashReport = ( BugTrackReport("trac.build.com"), )

      Application.ShowErrorToUser = false

     

if Environment.MachineName ~= /lap/: # dev machine

      Application.LogLevel = LogLevel.Debug

      Application.CrashReport = ( ErrorMessageReport("trac.build.com"), )

      Application.ShowErrorToUser = false

Trying to do the same in XML bring you right back to trying to debug XML. Since I don't know anyone except developer / IT admin that is going to touch a configuration file anyway, the claim that it is not readable to non-dev is not an issue. It is worth mentioning, though, that it is fairly easy to build a GUI over this.

time to read 5 min | 823 words

I just posted about semi statics, and now it is finally the post where I explain how I broke the external dependencies in my tests. That was the reason that pushed me to start talking about static in the first place.

I am using NHibernate to handle the data access (naturally), and when I started the project, there was no seperation in the tests from those that needs to touch the database (test that the mapping are working) and those that shouldn't (testing business logic).

I started to feel the pain recently, the tests took a long time to run, and the initial setup overhead was decidely not trivial, so even running a single test took too long. I decided that I really needed to make this seperation to integration tests and unit tests.

The problem was that I had code in both the tests and the business logic that assume that it can pull stuff from the database. I had the architecture I outlined in my previous post, where everything is accessible via the context, and everything is an interface. I did wrote a mocking library, so from there it was mainly going over each test and finding out if it is an integration test or a unit test.  This effort was not trivial, but it certainly paid off. I got a set of tests that run really fast, and I recently had to add another layer that significantly slows the tests. I was able to mock that in about half an hour (to handle all the premutations) and integrate it successuflly.

The integration tests are now much slower, but I don't care that much about their speed at the moment.

The setup for the unit tests is pretty complex right now, since I basically setup the whole environment via Rhino Mocks. All the tests inherits from a common base class that allows me to setup everything once for all the tests.  You can see what I do in this diagram. Just to note, the maximum cyclometic complexity here is 2.

(Image from clipboard).png

By the way, this is the single feature that I absolutely love in Refactor! and CodeRush (where it show you how long a method is).

The whole thing is simply based on code like this:

private void SetupMockObjectInSession(object obj, object key, Type type)

{

    Validation.NotNull(obj, "obj");

    SetupResult.For(_session.Load(type, key)).Return(obj);

    SetupResult.For(_session.Get(type, key)).Return(obj);

}

It gets a little more complex when I need to support complex queries, but it is still easy to grok.

The nice thing about it is that NHibernate is actually a deep infrastructure component in this application, I got a layer or two on top of it, which does all sort of nice things for me (like allowing me to ignore security, or logging, etc), which I am able to test, because I'm mocking the very bottom of the stack.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Challenge (75):
    01 Jul 2024 - Efficient snapshotable state
  2. Recording (14):
    19 Jun 2024 - Building a Database Engine in C# & .NET
  3. re (33):
    28 May 2024 - Secure Drop protocol
  4. Meta Blog (2):
    23 Jan 2024 - I'm a JS Developer now
  5. Production Postmortem (51):
    12 Dec 2023 - The Spawn of Denial of Service
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}