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,575
|
Comments: 51,188

Copyright ©️ Ayende Rahien 2004 — 2025

Privacy Policy · Terms
filter by tags archive
stack view grid view
  • architecture (606) rss
  • bugs (450) rss
  • challanges (123) rss
  • community (377) rss
  • databases (481) rss
  • design (893) rss
  • development (640) rss
  • hibernating-practices (71) rss
  • miscellaneous (592) rss
  • performance (397) rss
  • programming (1085) rss
  • raven (1442) rss
  • ravendb.net (526) rss
  • reviews (184) rss
  • 2025
    • May (7)
    • 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  
Nov 13 2008

Making code easier to read

time to read 1 min | 28 words

I didn't like this code:

image

I find this much easier to read:

image

Tweet Share Share 23 comments
Tags:
  • C#

  previous post next post  

Comments

Peter Ritchie
13 Nov 2008
18:23 PM
Peter Ritchie

How would you differentate between or conditions and and conditions?

Ayende Rahien
13 Nov 2008
18:26 PM
Ayende Rahien

It wouldn't

Peter Ritchie
13 Nov 2008
18:28 PM
Peter Ritchie

So, the And is implied... If you had to support both AND and OR conditions would you still do it that way?

Ayende Rahien
13 Nov 2008
18:28 PM
Ayende Rahien

No

Eric Hauser
13 Nov 2008
18:50 PM
Eric Hauser

The second one may be easier to read, but isn't it iterating over the collection twice?

Ayende Rahien
13 Nov 2008
18:55 PM
Ayende Rahien

No, it isn't.

Evaluation it lazy, ater all.

dru
13 Nov 2008
19:15 PM
dru

+1 Ayende

Justin Rudd
13 Nov 2008
19:42 PM
Justin Rudd

It's cleaner, but there is a subtle issue. You have to remember that Where calls are applied in reverse order (last to first).

In the former code containment in "Items" is checked before the "Type" check. In the latter code, the checks are the same order (Where is applied from last to first), but it reads differently. In this particular case, it may not matter, but in something like this...

var nonNullNameOfLength10 = AllItems.Where(x.Name != null && x.Name.Length == 10);

It reads well...oddly (IMO).

AllItems.Where(x.Name.Length == 10).Where(x.Name != null);

I've seen people stack the Where calls in the same order as the conditions. And that causes the code to break (you could be checking the length of a null name).

Ricky
13 Nov 2008
20:21 PM
Ricky

Why not

var irems = AllItems

.Where(x=> x.Type == parent.Type)

.Where(x=> !parent.Items.Contains(x);
Ricky
13 Nov 2008
20:21 PM
Ricky

oops forgot last parens :)

var irems = AllItems

.Where(x=> x.Type == parent.Type)

.Where(x=> !parent.Items.Contains(x));
Duarte Nunes
13 Nov 2008
20:23 PM
Duarte Nunes

@Justin Rudd

The calls are, indeed, applied in reverse order. But that means Where(x.Name != null)'s MoveNext() will call, before running its own code, Where(x.Name.Length == 10))'s MoveNext(), which could then throw a NullReferenceException. So, the code executes in the correct order (otherwise, as seen in your example, it would be really counterintuitive).

The only difference between Ayende's listings is that the latter, while much more readable, incurs one extra method call.

@Ricky

I'm guessing, readability.

Rik Hemsley
13 Nov 2008
22:39 PM
Rik Hemsley

I would probably format this as:

var items = AllItems.Where

(

x=>

  x.Type == parent.Type

  &&

  ! parent.Items.Contains(x)

);

Yes, I use a lot of vertical space, probably too much...

BTW I've said it before, but SubText doesn't seem very good for a developer's blog where code is posted.

Rik Hemsley
13 Nov 2008
22:40 PM
Rik Hemsley

Gah it screwed up the formatting... of course.

Benny Thomas
13 Nov 2008
23:41 PM
Benny Thomas

I like your thinking, Ayende!

Maybe you should make your own extension called And, that calls where, then it looks even better.

Bunter
14 Nov 2008
02:46 AM
Bunter

For me, first version is easier. I like the sound of "and" the && makes in my brain. But I would use in this case

.Where ( x => ( x.Type == parent.Type && !parent.Items.Contains(x)) )

I'm master of unnecessary parentheses.

Ben Hall
14 Nov 2008
03:01 AM
Ben Hall

I don't agree, and I really don't think this adds much terms of readability.

Personally, I find the code much more difficult to read due to the fact that we are implying the operator being used . It also means that if we want to use a mixture of && and || in the code, we will have two different approaches or having to flip conditions which sound people could easily misread.

Given the two following examples, I would always bit the latter.

var items = AllItems

.Where(x=> x.Type == parent.Type)

.Where(x=> !parent.Items.Contains(x));

var items = AllItems

.Where(x=> x.Type == parent.Type && !parent.Items.Contains(x));

Peter Morris
14 Nov 2008
09:29 AM
Peter Morris

I do something similar when I perform OCL queries

Person.allInstances

->select(givenName = 'Peter')

->select(familyName = 'Morris')

OR conditions need to be in their own select. I find it easier to read because a condition with lots of & needs to be mentally processed as a single element when reading the source, whereas multiple WHERE or ->SELECT can be read as smaller elements and I find them easier to read.

Ray Booysen
14 Nov 2008
16:28 PM
Ray Booysen

Based on the code below, you can see the where conditions are not done in reverse order:

Random r = new Random();

List <double values = new List <double();

for (int i =0; i < 10000; i++)

{

values.Add(r.NextDouble());

}

var result = values

.Where(d => { "Inner".Dump(); return true; })

.Where(d => { "Outer".Dump(); return true; });

result.Dump();

Ray Booysen
14 Nov 2008
16:55 PM
Ray Booysen

And of course, this was done with LinqPad. ;)

PandaWood
15 Nov 2008
03:24 AM
PandaWood

@Ben Hall - I think the point you're missing is that the Ayende's version has less to read, less to think about.

I could understand it and re-read later, just as fast. The alternative you provided, always requires more time parsing in my brain.

I get a bit worried when people don't see this. I do believe that your brain would read it quicker as well.

I am starting to think that the only people who prefer that type of unnecessarily verbose sort of statement, these days, are those whose are allowing aspects of their personality influence what should be a more scientific choice.

Assuming we're all in the business of programming for "business" Ayende's choice has got to be the right one.

If you're programming something lower level, maybe I'll bend a little.

configurator
16 Nov 2008
17:01 PM
configurator

What reverse order are you guys talking about? Could you elaborate a bit?

norbi
25 Dec 2008
23:29 PM
norbi

Hi*

Apart from readness, which for me second options creates more confusion, from my simple test it seems that these codes are not executing the same.

First is always evaluating the first statement, which is checking collection and that equality with parent.type is first true.

Second on the other hand applies filters as they are (hmm, it would be strange to apply pipeline in reverse order), and this is valid but with query expresions not operators. So if you would like to achive reverse execution you should write like this

var items = from x in AllItems

where x.type == parent.type

where parent.Items.Constains(x) == false

select x;

Regards!

norbi
25 Dec 2008
23:42 PM
norbi

Sorry for confusion, it's to late :/, execution is the same of course with expressions/operators.

So still Ayende is it by mistake this order?

regards!

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

  1. Optimizing the cost of clearing a set - 3 days from now
  2. Scaling HNSW in RavenDB: Optimizing for inadequate hardware - 5 days from now

There are posts all the way to May 14, 2025

RECENT SERIES

  1. RavenDB News (2):
    02 May 2025 - May 2025
  2. Recording (15):
    30 Apr 2025 - Practical AI Integration with RavenDB
  3. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
  4. RavenDB (13):
    02 Apr 2025 - .NET Aspire integration
  5. RavenDB 7.1 (6):
    18 Mar 2025 - One IO Ring to rule them all
View all series

RECENT COMMENTS

  • But in case you have nullability checks enabled (i.e. `<Nullable>enable</Nullable>`), then you'll have a compiler warning on ...
    By Samyon Ristov on The null check that didn't check for nulls
  • Grok wasn't *wrong*. It only said that `_items` can't be null for the condition to evaluate to `true`, but didn't say anythi...
    By Johannes Egger on The null check that didn't check for nulls
  • When I started enabling NRT, I remember I was initially confused when all variables (for reference types) declared with `var`...
    By riccardo on The null check that didn't check for nulls
  • That is surprising - I think of var as a shorthand that does not affect the final result of the compilation. I wouldn't expec...
    By Chris B on The null check that didn't check for nulls
  • "It is also about as friendly as a monkey with a sore tooth and an alcohol addiction." And I have to clean my monitor.
    By Tim on When racing the Heisenbug, code quality goes out the Windows

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}