-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IMHO: IDistributedLock should be public #10
Comments
Hi @nerumo. I'm glad you like the project and thank you for your thoughts. I agree that having an interface would make testing a bit easier. There are a few reasons why thus far I've kept it internal:
Definitely something to consider for a future release. |
Tnx for the explanation. I see that the IDistributedLock interface indeed is an internal "implementation detail".
Ok, fair enough. How a about an additional interface for each kind of lock?
The way mocking frameworks (moq, fakeiteasy etc.) work is, that they work (by far) best with interfaces. Every method that isn't an interface method or isn't virtual, can't be mocked with these frameworks. That's why I'd prefer an interface to work with.
If we wouldn't need to refactor it to an abstract base class and use additional interfaces, the change would be very safe and according to semver, this kind of change would be a minor change:
What do you think? Would adding new and separate interfaces for each lock address both of our concerns? |
@nerumo just to clarify on the interface compatibility point, my proposal is to follow the "abstract base classes as versionable interface" pattern seen in I haven't used FakeItEasy but I have use Moq extensively and it works really nicely with abstract base classes set up like interfaces (no logic or state in the ABC at all, just abstract/virtual methods). Does FakeItEasy only support interfaces? |
Thank you for the article link, someone could finally show me a downside of interfaces :). I'm no expert in library/framework design, but aren't many arguments in that article obsolete through the introduction of nuget and it's workflow? If you do an update of this lib, all applications must and will be recompiled anyway (since this lib won't be installed and referenced through the GAC or so). And then it would be terrible not to break compilation and throw a FakeItEasy works the same way as Moq, just more of the same ;). But working with interfaces is slightly different:
So long story short: I get your point and I don't mind mocking a an ABC, but for now I just work with my own interface to abstract the DistributedLock. Still looking forward for updates on this lib, thanks again. |
I find myself in need to mock this too. I'll share whatever wrapper/s I create here in the meantime. |
public interface ISqlDistributedReaderWriterLockFactory
{
ISqlDistributedReaderWriterLock Create(string lockName, string connectionString);
}
public class SqlDistributedReaderWriterLockFactory : ISqlDistributedReaderWriterLockFactory
{
public ISqlDistributedReaderWriterLock Create(string lockName, string connectionString)
=> new SqlDistributedReaderWriterLock(lockName, connectionString);
}
public interface ISqlDistributedReaderWriterLock
{
Task<IDisposable> TryAcquireWriteLockAsync(TimeSpan timeout = default, CancellationToken cancellationToken = default);
}
public class SqlDistributedReaderWriterLock : ISqlDistributedReaderWriterLock
{
private readonly Medallion.Threading.Sql.SqlDistributedReaderWriterLock _internalLock;
public SqlDistributedReaderWriterLock(string lockName, string connectionString)
{
_internalLock = new Medallion.Threading.Sql.SqlDistributedReaderWriterLock(lockName, connectionString);
}
public Task<IDisposable> TryAcquireWriteLockAsync(TimeSpan timeout = default, CancellationToken cancellationToken = default)
=> _internalLock.TryAcquireWriteLockAsync(timeout, cancellationToken);
} Autofac setup: builder.RegisterType<SqlDistributedReaderWriterLockFactory>().As<ISqlDistributedReaderWriterLockFactory>().SingleInstance(); |
@benmccallum just curious: is your goal with having an interface to abstract away which type of distributed lock you use or is it purely for mocking in unit tests? In other words, would having various methods be virtual be equally useful? |
@madelson, in my case it's to facilitate mocking in unit tests. Having the |
IMO, it should not be the responsibility of this library to expose an interface for the sake of abstraction. If this library did expose an interface that you relied on, you'd be defeating the purpose by creating a dependency on this whole library for anything downstream of your initial implementation. I like @benmccallum's implementation |
IMHO: The IDistributedLock should be public. Because:
Btw, thanks for the good work in this project
The text was updated successfully, but these errors were encountered: