Skip to content

Interfaces #182

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

Closed
wants to merge 16 commits into from
Closed

Interfaces #182

wants to merge 16 commits into from

Conversation

haacked
Copy link
Contributor

@haacked haacked commented Jun 14, 2012

This pull request adds some interfaces to more of the commonly used types. In one case, instead of an interface, I just changed the ctor from internal to public.

I also added unit tests for RepositoryExtensions that don't require creating an actual repository as a demonstration of how these interfaces allow isolation in unit tests.

@yorah
Copy link
Contributor

yorah commented Jun 14, 2012

@haacked This topic triggered my curiosity, and after playing a bit with Moq I think I have a slightly different proposal, which I think would fit the need to make LibGit2Sharp more testable.

The idea is that an interface makes sense on classes exposing operations/behaviors (like IRepository), but not necessarily on classes representing git objects (Branch, Commit ...). However, in order to make those classes test-friendly (i.e.: mockable), I just needed to add a protected empty constructor and make the needed properties virtual.

Would you please be so kind as to take a look at my interfaces branch, and tell me what you think about it?

Please note that I only implemented this proposal on a few classes, in order to get your feedback. In case you like it, I will gladly extend the scope to cover the same classes that you did.

@haacked
Copy link
Contributor Author

haacked commented Jun 14, 2012

The idea is that an interface makes sense on classes exposing operations/behaviors (like IRepository),
but not necessarily on classes representing git objects (Branch, Commit ...).

Citation needed. :) Why doesn't an interface make sense on classes representing git objects? They also have behavior.

{
internal DetachedHead(Repository repo, Reference reference)
public DetachedHead(Repository repo, Reference reference)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What makes this required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure. I changed it back.

@yorah
Copy link
Contributor

yorah commented Jun 15, 2012

Citation needed. :)

I had no citation in mind when I wrote this, I was merely voicing out my opinion :)

I tried to organize my thoughts, and here is why I proposed the "protected constructor & virtual members" approach:

  • When I create an interface, and there is only one implementation of this interface, I tend to think of it as a code smell. I usually take a step back and check if I really need it.
  • For mocking purposes, the protected constructor/virtual members seems to completely meet the need, while not extending the exposed surface of the API.

Why doesn't an interface make sense on classes representing git objects? They also have behavior.

Actually, for me, they are rather just objects used to hold data related to the content of a repository. The real operation/behavior/action logic is accessed through the Repository.

On a separate note, I just realized I commented on your PR, instead of commenting on #138, where you were already having discussions about the same topic. Would you like to switch back there?

Assert.NotNull(branch2);
Assert.Equal("br2", branch2.Name);

Assert.Equal(branch, branch2);
Assert.True((branch2 == branch));
Assert.True(((Branch)branch2 == (Branch)branch));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very keen on this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately interfaces don't allow operator overloads as extension methods. I could just delete this line or change it to:

Assert.True(branch2.Equals(branch));

Which would you prefer?

Per code review comments
@haacked
Copy link
Contributor Author

haacked commented Jun 15, 2012

@yorah OK, I had a chat with @nulltoken about this and long story short, let's go with the approach you described.

Interfaces vs classes with virtuals is a debate as old as time and I'm just not too keen to rehash it over and over. The most important thing to me is to get changes in LibGit2Sharp that will enable our testing scenarios and I believe your changes meet that need and fit the design sensibilities of LibGit2Sharp.

Bonus, they are certainly much less breaking than my changes are. :)

Are you going to tackle this? Do you need any help from me?

Thanks!

@haacked haacked closed this Jun 15, 2012
@yorah
Copy link
Contributor

yorah commented Jun 15, 2012

It would be a pleasure for me to tackle this! I will make the changes based on what you did (the assumption being that everything you put as interfaces in this PR should be testable), so the scope should be identical.

I will make a pull request tomorrow. It would be nice of you to review it when it's done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants