I've been trying for a while to write clean and testable code, with the help of DI and abstractions.  
I found myself guilty of *service-itis*, creating 3 or 4 interfaces for something that clearly doesn't need it. So I decided to relax, and only abstract what **really** needs it.

I'm faced with a problem where I'm not sure what is the best way to solve.  
Let me explain, the requirements are pretty straightforward.  

> The application must determine, when a user wants to sign up, if he's blacklisted, based on a couple of information about the user  
> The service providing the information about the possible blacklisting of the player is external, and not accessible from our development platforms.

OK, I see here a need for an interface to abstract the blacklisting service so I can test properly the actions that rely on the fact that a user may be blacklisted, so I come up with a cery basic interface:


<!-- language: c# -->

    public interface IUserBlacklistService
    {
    	Boolean IsUserBlacklisted(IsUserBlacklistedRequest request);
    }
    
    public class IsUserBlacklistedRequest
    {
        public String FirstName
        {
    	    get;
    	    set;
        }
    
        public String LastName
        {
    	    get;
    	    set;
        }
    
        public DateTime BirthDate
        {
    	    get;
    	    set;
        }
    
        public String BirthCity
        {
    	    get;
    	    set;
        }
    
        public String BirthCountry
        {
    	    get;
    	    set;
        }
    
        public String BirthDepartment
        {
    	    get;
    	    set;
        }
    }

Now, the actual service I have to deal with works this way:

> The blacklist is exposed as a DNS server, meaning I have to make a DNS query, asking for *hashofsomeoftheuserinformation.somedomain.tld*, something like *firstnamelastnamebirthdate.somedomain.tld*  
> If the provided information matches entries in the blacklist, the DNS server replies with TXT records containing:  
> 
 - A set of information for French user
 - Another set of information for other users

> I then have to match this information with the information the user filled to know if he's blacklisted or not.

At this point, I'm thinking of creating the `DnsUserBlacklistService` class implementing the `IUserBlacklistService`, but also of creating another abstraction representing **only** the DNS query, let's call it `IDnsService`, which will look like:

<!-- language: c# -->

    public interface IDnsService
    {
        IEnumerable<String> GetRecords(String queriedDomain);
    }

This, in my mind, will allow me to safely test:

 - That the queried domain is the right one, so I know I build the hash correctly from the user information
 - That the matching between the returned TXT records and the user information is correct

So the class `DnsUserBlacklistService` would look like this:

<!-- language: c# -->

    public class DnsUserBlacklistService: IDnsUserBlacklistService
    {
    	private readonly IDnsService _dnsService;
    	private readonly String _domain;
    
    	public DnsUserBlacklistService(IDnsService dnservice, String domain)
    	{
    		_dnsService = dnsService;
    		_domain = domain;
    	}
    
    	public Boolean IsUserBlacklisted(IsUserBlacklistedRequest request)
    	{
    		var subDomainToQuery = GetSubDomainToQuery(request);
    		var fullDomainToQuery = String.Format("{0}.{1}", subDomainToQuery, _domain);
    
    		var dnsRecords = _dnsService.GetRecords(fullDomainToQuery);
    		if (dnsRecords != null && dnsRecords.Any())
    		{
    			// Match between records and user information
    			// Note: I know I shouldn't write pseudo-code, but this part
    			// is really unrelevant to the question
    		}
    
    		// If no DNS records, assume the user is not blacklisted
    		return false;
    	}
    
    	private String GetSubDomainToQuery(IsUserBlacklistedRequest request)
    	{
    		return String.Concat(
    			request.FirstName,
    			request.LastName,
    			request.BirthDate.ToString("yyyyMMdd")
    		);
    	}
    }

It seems to me that having everything in the `DnsUserBlacklistService` class wouldn't allow me to test thoroughly the process. I could have some `internal` methods being exposed to the test project with an `[InternalsVisibleTo]` attribute, like the hash construction, but that doesn't abstract me from the actual DNS query, which is **the one** external service I don't own.

In the end, my question is: **am I going too far with abstractions?**  
Maybe some thoughts on this particular example could help me decide in the future where to stop.

  [1]: http://stackoverflow.com/questions/25745941/how-far-should-i-go-with-abstraction