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)
Deep Dive into RavenDB webinars
  previous post next post  
Nov 12 2010

What is wrong with this API?

time to read 1 min | 54 words

Originally posted at 11/11/2010

This is part of a base class, and we need to provide a way to veto messages for extensions.

image

Can you figure out what is wrong with this API?

Tweet Share Share 43 comments

  previous post next post  

Comments

Torkel
12 Nov 2010
10:18 AM
Torkel

If the function only decides if a message should be vetoed or not it should reflect that. That is name the function ShouldVetoMessage

configurator
12 Nov 2010
10:20 AM
configurator

What does true (or false) mean in the overriding function? A boolean seems out of place here. An enum would do better.

configurator
12 Nov 2010
10:22 AM
configurator

(Or renaming the function in a more positive tone to avoid double negatives - ValidateMessage maybe or some such)

stoo
12 Nov 2010
10:26 AM
stoo

You're using a class rather than an interface for the parameter type.. ?

(unless you've chosen IncomingMessage to be an abstract base class tfor all IncomingMessage types)

James Gregory
12 Nov 2010
10:33 AM
James Gregory

The doc comment is confusing?

stoo
12 Nov 2010
10:35 AM
stoo

... reading it again I think Torkel has it ...

the Function 'VetoMessage' is a verb and a noun ... so it sounds like it has side effects... it doesn't ..so it def' should be 'ShouldVetoMessage'

'ValidateMessage' would imply that it's performing validation.. so prob' wouldn;t go for that as there may be any number of reasons you might want to veto a valid message

Steve Py
12 Nov 2010
10:36 AM
Steve Py

Hmm. +1 for confusing documentation.

Not sure but if this is dealing with an incoming message it might be tempting to attempt to call it from a base constructor, which would be bad.

Krzysztof Koźmic
12 Nov 2010
10:37 AM
Krzysztof Koźmic

Other than as James noted the XML comment is confusing the API itself is perfectly fine

Andreyg
12 Nov 2010
10:39 AM
Andreyg

The method name is confusing. Should be something like ShouldVetoMessage(...)

addy santo
12 Nov 2010
10:43 AM
addy santo

all of the above, + if vetoing is important functionality then I would make this abstract. If the inheriting classes are written by the consumers (ie not Oren) then they should be forced to provide their own implementation, otherwise everyone will default to the "return false" :)

Rik Hemsley
12 Nov 2010
10:48 AM
Rik Hemsley

It's implied by the fact it's not abstract that this implementation has real meaning. Does it really make sense for this particular class to make a decision on whether or not to veto? If not, it should be abstract.

Also, as others have noted, the XML comment is confusing. Its grammar is also broken. It should also be removed and the method renamed, as in this case it would be simple to name the method such that it was self-documenting.

So, as others have noted, it should be renamed, but 'ShouldVetoMessage' doesn't convey that it will not be 'enqueued'. So, based on the information provided, it's most likely it should be named 'ShouldBeEnqueued'.

Three WTFs, two lines of code. Impressive.

Steve Py
12 Nov 2010
11:03 AM
Steve Py

Alternatively, I might opt instead for something along the lines of a "Vetoed" flag inside of IncomingMessage, similar to "Cancelled" or "Handled" in various event models. This way anything that touches something designated as an incoming message has the chance to veto it in whatever relevant call they can override.

George C.
12 Nov 2010
11:09 AM
George C.

all of the above + use Nonvirtual interface idiom

Ayende Rahien
12 Nov 2010
11:20 AM
Ayende Rahien

Rik,

This is the default impl, sub classes can choose to override this method or not.

The XML comment grammer is pretty much the standard for me, I am afraid, that isn't what I meant.

And the problem isn't in the method name either

Evgeny Shapiro
12 Nov 2010
11:30 AM
Evgeny Shapiro

Why should one subclass? Interceptor might be a more appropriate solution.

Sean Kearon
12 Nov 2010
11:33 AM
Sean Kearon

Usually you will accept the message, so the default should return false and let specialisms do the vetoing.

alwin
12 Nov 2010
11:36 AM
alwin

Well for me it's not clear if true means that this message is passed or denied.

Maybe this would be better?

public virtual bool AllowMessage(IncomingMessage message){

return true;

}

Stefan Wenig
12 Nov 2010
11:52 AM
Stefan Wenig

mind to give some context? the problem might be that you need to derive from some (what?) base class only to get to veto - and then maybe someone else derives too and now you got two competing implementations? might be better to enlist everyone whoi might need to veto, maybe using cancelable events.

Oleg
12 Nov 2010
11:53 AM
Oleg

We cannot tell by looking at signature what exactly it's return value refers to?

Andrew
12 Nov 2010
11:57 AM
Andrew

There's no way to explicitly allow a message (and prevent a veto)?

You may want a VetoResult { Permit, Deny, Ignored } result instead so that an extension can explicitly permit or deny the message from being propagated; or decide to have no action on the message (Ignored).

wouzer
12 Nov 2010
12:01 PM
wouzer

Maybe you are missing the context to base the decision on?

public virtual bool VetoMessage(QueueContext context, IncomingMessage message)

{

return true;

}

Koen
12 Nov 2010
12:02 PM
Koen

Veto-ing is about overruling in a hierarchical system. A concrete class can inherit the base class and execute logic to decide if a message is blocked as some sort of superior.

However, you can inherit from that class again, override the method again and at the same time overrule your "superior". I guess that's a flaw...

Dan Plaskon
12 Nov 2010
12:02 PM
Dan Plaskon

I think Andrew's on the right track..I think more context would be helpful here...eg how is VetoMessage called/used for these plugins by the infrastructure?

Dan Plaskon
12 Nov 2010
12:05 PM
Dan Plaskon

@Koen: Couldn't that be prevented by sealing the class though?

Nick
12 Nov 2010
12:29 PM
Nick

I think the comment does not make sense.

Adam B
12 Nov 2010
12:36 PM
Adam B

Violates Open/Closed principal? Looks open for modification.

Andrey Shchekin
12 Nov 2010
12:41 PM
Andrey Shchekin

It does not allow to specify a reason?

Mike Minutillo
12 Nov 2010
12:47 PM
Mike Minutillo

Callers will (potentially) be able to tell who vetoed a message but not why (unless you have some very fine grained message checkers). It would be better to have something like:

public virtual void VetoMessage(IncomingMessage message, VetoContext context) {

if( someCondition ) {

context.VetoMessage(someReason);

}

}

Trey
12 Nov 2010
13:29 PM
Trey

The fact that the method is public seems to imply that the decision to veto can be bypassed (i.e. - It seems to be the responsibility of the caller to choose whether or not to evaluate the possibility of vetoing the message).

The exact context and responsibility of the example itself is unclear to me (is the method intended to actually perform the logic for vetoing the message, or simply decide whether or not the message should be vetoed.....what is the overall responsibility of the base class, etc.), so the decision to make this public could very well be by design. Just my humble two cents. :)

Brian Frantz
12 Nov 2010
13:43 PM
Brian Frantz

Should be a protected method - meant for internal logic, not for the end-user of the class.

WishCow
12 Nov 2010
13:53 PM
WishCow

The method's name is misleading, because VetoMessage(message) leads you to believe that you pass a message that you want to veto, but the doc comment states that the method will only decide if the message is vetoed, or not, and does not mark a message as vetoed.

The method should be renamed to isVetoed(message).

Jason Meckley
12 Nov 2010
14:13 PM
Jason Meckley

My first thought was the context is missing. And I still think that is the number 1 problem with the method. After reading the comments I agree that the name of the message should be changed to ShouldVetoMessage.

VetoMessage sounds like this will veto, not whether is should veto.

jonnii
12 Nov 2010
15:05 PM
jonnii

I know this has already been said but I believe that the reason is because it doesn't give the end user enough discovery as to why the message was vetoed.

I'd rather have something like (forgive the crappy names):

public virtual MessageVeto VetoMessage(IncomingMessage message){

return MessageVeto.MessageOk;

}

where MessageVeto is something like:

class VetoMessage{

static VetoMessage Ok(){...}

 string Reason { get; set; }

 bool IsVetoed { get { !string.IsNullOrEmpty(Reason); } }

}

This means if you're using the API for the first time and you're wondering why your messages are being vetoed you can look at the reason and make the change.

The other option is that you can have an enum as the return type which gives you more indication as to why the message was vetoed if there are classifications, which means you don't want to add another class, that's still more discoverable than a boolean and gives you options to add more reasons later without, hopefully, breaking the API.

If you absolutely must return a boolean for some reason you could add an event that gets raised when a message is vetoed with a reason.

jonnii
12 Nov 2010
15:07 PM
jonnii

One more thing, this is very similar to what Mike suggested, but I prefer returning the result instead of putting it in a context because that way you can write:

if(foo.VetoMessage(m).IsVetoed){...}

instead of

var context = ..,;

foo.VetoMessage(m, context);

if(context.IsVetoed()){...}

And it means you can make the response immutable, another win for SCIENCE!

Richard Dingwall
12 Nov 2010
15:26 PM
Richard Dingwall

If there are multiple extensions each with this method, which one do you listen to?

Tom
12 Nov 2010
16:11 PM
Tom

Should return an int or enum for greater flexability

lowds
12 Nov 2010
17:22 PM
lowds

Whether an incoming message has been vetoed or not represents a state of the message and this state would ideally be a property on the message itself.

Having a method on the IncomingMessage class that takes a list of extensions would solve this, something like:

message.AssertVeto(extensions);

(or what ever a better name for AssertVeto would be)

This would let the message track it's own state and then implement any additional logic required rather than have this in a seperate controller-like class. Any other class can then query the state of the message rather than pass around a boolean.

Equally if you wanted to have a message that cannot be vetoed you can create a subclass of IncomingMessage and override the AssertVeto implementation.

Jackknife
12 Nov 2010
18:23 PM
Jackknife

Disencourages ask - don't tell?

Sony Mathew
12 Nov 2010
18:38 PM
Sony Mathew

There is nothing technically wrong with this API. However, it would be better if this API were exposed via a modified Observer pattern.

E.g.

addVetoAuthority(VetoAuthority v)

where:

interface VetoAuthority {

boolean isVetoed(IncomingMessage m);

}

Sony

Michael D.
12 Nov 2010
19:21 PM
Michael D.

Inability to chain filters that can prevent from the message from being sent?

Kevin L
12 Nov 2010
23:08 PM
Kevin L

On the surface, this method looks fine, but a descendant class being allowed to override the method creates a grammatical ambiguity:

public bool override VetoMessage(,,,) {...}

By definition a veto cannot be over-ridden.

David Cuccia
13 Nov 2010
00:29 AM
David Cuccia

The method doesn't make sense - if the caller has already decided to veto the message, why would it call a method just to get a boolean back to say that it was vetoed (or not).

Instead, the return type should be void and the default implementation should either do nothing or actually veto the message.

David Cuccia
13 Nov 2010
21:07 PM
David Cuccia

(Or the method name should be TryVeto)

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
}