Oren Eini

aka Ayende Rahien

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,578
|
Comments: 51,203

Copyright ©️ Ayende Rahien 2004 — 2025

Privacy Policy · Terms
filter by tags archive
stack view grid view
  • architecture (608) rss
  • bugs (450) rss
  • challanges (123) rss
  • community (378) rss
  • databases (481) rss
  • design (894) rss
  • development (640) rss
  • hibernating-practices (71) rss
  • miscellaneous (592) rss
  • performance (397) rss
  • programming (1085) rss
  • raven (1445) rss
  • ravendb.net (529) rss
  • reviews (184) rss
  • 2025
    • May (10)
    • April (10)
    • March (10)
    • February (7)
    • January (12)
  • 2024
    • December (3)
    • November (2)
    • October (1)
    • September (3)
    • August (5)
    • July (10)
    • June (4)
    • May (6)
    • April (2)
    • March (8)
    • February (2)
    • January (14)
  • 2023
    • December (4)
    • October (4)
    • September (6)
    • August (12)
    • July (5)
    • June (15)
    • May (3)
    • April (11)
    • March (5)
    • February (5)
    • January (8)
  • 2022
    • December (5)
    • November (7)
    • October (7)
    • September (9)
    • August (10)
    • July (15)
    • June (12)
    • May (9)
    • April (14)
    • March (15)
    • February (13)
    • January (16)
  • 2021
    • December (23)
    • November (20)
    • October (16)
    • September (6)
    • August (16)
    • July (11)
    • June (16)
    • May (4)
    • April (10)
    • March (11)
    • February (15)
    • January (14)
  • 2020
    • December (10)
    • November (13)
    • October (15)
    • September (6)
    • August (9)
    • July (9)
    • June (17)
    • May (15)
    • April (14)
    • March (21)
    • February (16)
    • January (13)
  • 2019
    • December (17)
    • November (14)
    • October (16)
    • September (10)
    • August (8)
    • July (16)
    • June (11)
    • May (13)
    • April (18)
    • March (12)
    • February (19)
    • January (23)
  • 2018
    • December (15)
    • November (14)
    • October (19)
    • September (18)
    • August (23)
    • July (20)
    • June (20)
    • May (23)
    • April (15)
    • March (23)
    • February (19)
    • January (23)
  • 2017
    • December (21)
    • November (24)
    • October (22)
    • September (21)
    • August (23)
    • July (21)
    • June (24)
    • May (21)
    • April (21)
    • March (23)
    • February (20)
    • January (23)
  • 2016
    • December (17)
    • November (18)
    • October (22)
    • September (18)
    • August (23)
    • July (22)
    • June (17)
    • May (24)
    • April (16)
    • March (16)
    • February (21)
    • January (21)
  • 2015
    • December (5)
    • November (10)
    • October (9)
    • September (17)
    • August (20)
    • July (17)
    • June (4)
    • May (12)
    • April (9)
    • March (8)
    • February (25)
    • January (17)
  • 2014
    • December (22)
    • November (19)
    • October (21)
    • September (37)
    • August (24)
    • July (23)
    • June (13)
    • May (19)
    • April (24)
    • March (23)
    • February (21)
    • January (24)
  • 2013
    • December (23)
    • November (29)
    • October (27)
    • September (26)
    • August (24)
    • July (24)
    • June (23)
    • May (25)
    • April (26)
    • March (24)
    • February (24)
    • January (21)
  • 2012
    • December (19)
    • November (22)
    • October (27)
    • September (24)
    • August (30)
    • July (23)
    • June (25)
    • May (23)
    • April (25)
    • March (25)
    • February (28)
    • January (24)
  • 2011
    • December (17)
    • November (14)
    • October (24)
    • September (28)
    • August (27)
    • July (30)
    • June (19)
    • May (16)
    • April (30)
    • March (23)
    • February (11)
    • January (26)
  • 2010
    • December (29)
    • November (28)
    • October (35)
    • September (33)
    • August (44)
    • July (17)
    • June (20)
    • May (53)
    • April (29)
    • March (35)
    • February (33)
    • January (36)
  • 2009
    • December (37)
    • November (35)
    • October (53)
    • September (60)
    • August (66)
    • July (29)
    • June (24)
    • May (52)
    • April (63)
    • March (35)
    • February (53)
    • January (50)
  • 2008
    • December (58)
    • November (65)
    • October (46)
    • September (48)
    • August (96)
    • July (87)
    • June (45)
    • May (51)
    • April (52)
    • March (70)
    • February (43)
    • January (49)
  • 2007
    • December (100)
    • November (52)
    • October (109)
    • September (68)
    • August (80)
    • July (56)
    • June (150)
    • May (115)
    • April (73)
    • March (124)
    • February (102)
    • January (68)
  • 2006
    • December (95)
    • November (53)
    • October (120)
    • September (57)
    • August (88)
    • July (54)
    • June (103)
    • May (89)
    • April (84)
    • March (143)
    • February (78)
    • January (64)
  • 2005
    • December (70)
    • November (97)
    • October (91)
    • September (61)
    • August (74)
    • July (92)
    • June (100)
    • May (53)
    • April (42)
    • March (41)
    • February (84)
    • January (31)
  • 2004
    • December (49)
    • November (26)
    • October (26)
    • September (6)
    • April (10)
RavenDB Workshops - Deep dive into practical use of Document Data Modeling
  previous post next post  
May 16 2011

A public request for code review: Raccoon Blog

time to read 1 min | 38 words

I really like this idea:

image

The code is available here: http://github.com/ayende/RaccoonBlog/

Tweet Share Share 22 comments
Tags:
  • Blog
  • Reviews

  previous post next post  

Comments

Dennis
17 May 2011
04:21 AM
Dennis

normalize-crlf.ps1

I know it is not part of your main code, but still have to give you a review :P You touch every file, no matter if they need changing or not...

Use this in the inner loop to check (It is a bit overkill to read the whole file, but you are converting small files)

$fn = $_.FullName<br/> if ([System.IO.File]::ReadAllText($fn).Contains(";`n"))<br/> {<br/> ( Get-Content $fn -ReadCount 9999999 ) | Set-Content $fn<br/> }

Rafal
17 May 2011
07:10 AM
Rafal

And now your blog has became self-perpetuating: You blog about creating a blog.

firo
17 May 2011
08:17 AM
firo

just a small thing:

    public static string ResolveTags(string[] tags)
    {
        string result = tags.Aggregate(string.Empty, (current, tag) => current + (TagsSeparator + tag));
        return result.Trim(TagsSeparator);
    }

Can be written as:

    public static string ResolveTags(string[] tags)
    {
        return string.Join(TagsSeparator.ToString(), tags).Trim(TagsSeparator);
    }

ToString is only needed, if the TagsSeparator is char and not string. Simple tests show, its 4 times faster. I know i doesnt really matter much, but i think join is easier to understand than an aggregate.

Remco
17 May 2011
10:30 AM
Remco

I just came accros this piece of code in PostDetailsController (line 48/49):

        if (vm.Post.Slug != slug)
            return RedirectToActionPermanent("Details", new { id, vm.Post.Slug });

This can be moved to line 33. and written as:

        var postslug = SlugConverter.TitleToSlag(post.Title)
        if (postslug != slug)
            return RedirectToActionPermanent("Details", new { id, postslug });

this avoids the unneccesary loading of comments and creation/mapping of the viewmodel (which is not used because of the redirect).

also note the spelling mistake in TitleToSlag :-)

Itamar
17 May 2011
12:45 PM
Itamar

There is also a double redirect, meaning unnecessary requests from the server. For example a request to:

http://ayende.com/Blog/archive/2009/03/08/designing-a-document-database.aspx

which is a search result in Google, will first respond with 301 to:

http://ayende.com/blog/archive/2009/03/08/designing-a-document-database.aspx

and a request to that page will respond with a 301 to the now real URL:

/blog/3897/designing-a-document-database

And now, writing this post, the post preview doesn't seem to handle URLs. Hopefully the posted comment will not look to awful...

Dan Plaskon
17 May 2011
13:12 PM
Dan Plaskon

I'm thinking someone should review the future post code; as they don't seem to be automatically posting properly ;)

tobi
17 May 2011
13:38 PM
tobi

"double redirect" this is what I meant when I was talking about SEO. redirect chains are counterintuitively bad for propagating the accumulated trust the old page had.

Ayende Rahien
17 May 2011
13:48 PM
Ayende Rahien

Firo, Thanks, I implemented your suggestion. Please note that we don't actually need the Trim now.

Ayende Rahien
17 May 2011
13:49 PM
Ayende Rahien

Dennis, I don't really care about touching all the files. Does it matter in any way?

Ayende Rahien
17 May 2011
13:52 PM
Ayende Rahien

Remco, That is actually intentional, because is avoids breaking the creation of PostViewModel into several parts. We accept the loading of comments in that scenario as acceptable to keep the code looking better.

Ayende Rahien
17 May 2011
13:53 PM
Ayende Rahien

Itamar, That is actually two different things happening here. The first is an SEO filter inside IIS that is converting all URLs to lower case. The second is the actual application redirect.

We'll probably do additional work on the comment preview as well, yes.

Ayende Rahien
17 May 2011
14:05 PM
Ayende Rahien

Tobi, That is a good point, I'll take care of that.

Giedrius Banaitis
17 May 2011
14:07 PM
Giedrius Banaitis

is it just me, or there's no unit tests?

Steves
17 May 2011
15:06 PM
Steves

@Giedrius Banaitis

http://ayende.com/blog/4092/reviewing-nerddinner

https://github.com/ayende/RaccoonBlog/blob/master/src/RaccoonBlog.IntegrationTests/Views/Post/Details.cs

;-) let's face it, who wants to code a few tens of lines of code (I am counting code to define the test fixture, usings and all the boiler plate code) to test that a method with "return new Something()" really returns Something.

There should be somebody who has balls to admin this :-))

Ayende Rahien
17 May 2011
15:11 PM
Ayende Rahien

Steves, Thanks, that is actually dead code, which will be removed soon.

Frank Quednau
17 May 2011
22:47 PM
Frank Quednau

PostAdminController.CommentsAdmin is marked by NDepend as being fairly ugly. I have to say, I agree.

Since you do seem to like using readonly as well, in the AskimetService you can set the key to readonly, and get rid of the document session instance var.

There are a couple other findings, but all in all pretty undramatic.

Giedrius Banaitis
18 May 2011
05:54 AM
Giedrius Banaitis

@Steves - well there are several things: a) first first class i've opened breaks the rantings posted on your link - I mean several classes in same file and one of them is controller? b) both commands have more than 10 lines (although there's no such rule - if there's more than 10 lines - test it), so i think they are quite complicated, first of all, because they would be not easy testable without refactoring (because you would struggle mocking smtp client or akismet service). All this ranting from my side is just because i see different approach in Ayendes code (talking about this blog engine only, haven't seen much code on other his projects) - he is not trying to make everything mockable and easy testable, question is if that is a good idea.

Remco
18 May 2011
14:25 PM
Remco

@Ayende

I understand you want to keep things simple.

But look at PostAdminController:

In the Details(...) method this construct is also used (first map post to viewmodel. then check generated slug against slug parameter)

This is good in the sence that it hides the slug generation logic (it's deep hidden in a automapper profile, I don't like that either, but that's not my point right now).

Moving along to line 132 of the same controller (in the 'ugly' (not my words) CommentsAdmin method). SlugConverter is used directly!

So I don't really get why you don't want to use this SlugConverter directly in the other methods to gain some performance.

Remco

BFC
18 May 2011
15:14 PM
BFC

@Ayende

I am checking the structure of the solution, and trying to understand how you organize your artifacts.

I am confused about the Common, Infrastructure and Helpers folder.

For example, - why you put the class LowercaseRoute in the Common folder instead of the Infrastrucure folder. - why you put the action filter AjaxOnlyAttribute in the Helpers\Attributes folder and the RavenActionFilter inside Infrastructure\Controllers

One more question: the Services folder contains both what you are exposing (MetaWeblog) and consuming (Askimet) right? I think the term Service is very ambiguous. For example, let's say that I have a LoggingService: would you put the class inside the Infrastructure folder or Services folder?

My concern about the solution structure is to have all team members aligned, and not have think too much where should I put some class? My team is checking RaccoonBlog trying to learn that it is possible to have things well done without an heavy architecure (repositories, dependency injection, too mucch tiers, etc.)

Ayende Rahien
19 May 2011
08:57 AM
Ayende Rahien

Frank, Good suggestions for both, I refactored CommentsAdmin and AskimetService

Ayende Rahien
19 May 2011
08:59 AM
Ayende Rahien

Giedrius, Regarding testing, you need to look at my posts about where testing have significant value, and where they don't

Ayende Rahien
19 May 2011
09:03 AM
Ayende Rahien

BFC,

Good point, I've merged all three (Helpers, Common, Infrastructure) to a single location (Infrastructure).

Services, for me, are for interaction points with external stuff. Logging is internal, it would go in the infrastructure.

Comment preview

Comments have been closed on this topic.

Markdown formatting

ESC to close

Markdown turns plain text formatting into fancy HTML formatting.

Phrase Emphasis

*italic*   **bold**
_italic_   __bold__

Links

Inline:

An [example](http://url.com/ "Title")

Reference-style labels (titles are optional):

An [example][id]. Then, anywhere
else in the doc, define the link:
  [id]: http://example.com/  "Title"

Images

Inline (titles are optional):

![alt text](/path/img.jpg "Title")

Reference-style:

![alt text][id]
[id]: /url/to/img.jpg "Title"

Headers

Setext-style:

Header 1
========
Header 2
--------

atx-style (closing #'s are optional):

# Header 1 #
## Header 2 ##
###### Header 6

Lists

Ordered, without paragraphs:

1.  Foo
2.  Bar

Unordered, with paragraphs:

*   A list item.
    With multiple paragraphs.
*   Bar

You can nest them:

*   Abacus
    * answer
*   Bubbles
    1.  bunk
    2.  bupkis
        * BELITTLER
    3. burper
*   Cunning

Blockquotes

> Email-style angle brackets
> are used for blockquotes.
> > And, they can be nested.
> #### Headers in blockquotes
> 
> * You can quote a list.
> * Etc.

Horizontal Rules

Three or more dashes or asterisks:

---
* * *
- - - - 

Manual Line Breaks

End a line with two or more spaces:

Roses are red,   
Violets are blue.

Fenced Code Blocks

Code blocks delimited by 3 or more backticks or tildas:

```
This is a preformatted
code block
```

Header IDs

Set the id of headings with {#<id>} at end of heading line:

## My Heading {#myheading}

Tables

Fruit    |Color
---------|----------
Apples   |Red
Pears	 |Green
Bananas  |Yellow

Definition Lists

Term 1
: Definition 1
Term 2
: Definition 2

Footnotes

Body text with a footnote [^1]
[^1]: Footnote text here

Abbreviations

MDD <- will have title
*[MDD]: MarkdownDeep

 

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  2. Webinar (6):
    27 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  3. RavenDB News (2):
    02 May 2025 - May 2025
  4. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
  5. RavenDB (13):
    02 Apr 2025 - .NET Aspire integration
View all series

RECENT COMMENTS

  • What a massive presentation! As a person who spent some time with a db written in .NET I can strongly relate to some points. ...
    By Scooletz on Recording: RavenDB's Upcoming Optimizations Deep Dive
  • I’d love to learn your thoughts on SPANN https://arxiv.org/abs/2111.08566 that with centroids and keeping the posting lists s...
    By Scooletz on Comparing DiskANN in SQL Server & HNSW in RavenDB
  • Joel, The DiskANN paper talks about it being viable for more than a billion vectors datasets.  In such a scenario, it would ...
    By Oren Eini on Comparing DiskANN in SQL Server & HNSW in RavenDB
  • Do you know why they chose DiskANN? These things are usually about tradeoffs but it seems DiskANN is just worse in every way.
    By Joel on Comparing DiskANN in SQL Server & HNSW in RavenDB
  • Scooletz, Yes, we look at other stuff. Most of those are _not_ allowing you to build themselves incrementally nor are they...
    By Oren Eini on Scaling HNSW in RavenDB: Optimizing for inadequate hardware

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}