At which point should YAGNI take precedence against good coding practices and vice versa?  I'm working on a project at work and want to slowly introduce good code standards to my co-workers (currently there are none and everything is just kind of hacked together without rhyme or reason), but after creating a series of classes (we don't do TDD, or sadly any kind of unit testing at all) I took a step back and thought it's violating YAGNI because I pretty much know with certainty that we don't require the need to extend some of these classes.

Here's a concrete example of what I mean: I have a data access layer wrapping a set of stored procedures, which uses a rudimentary Repository-style pattern with basic CRUD functions.  Since there are a handful of methods that all my repository classes need, I created a generic interface for my repositories, called IRepository.  However, I then created a "marker" interface (i.e. interface that doesn't add any new functionality) for each type of repository (e.g. ICustomerRepository) and the concrete class implements that.  I've done the same thing with a Factory implementation to build the business objects from DataReaders/DataSets returned by the Stored Procedure; the signature of my repository class tends to look something like this:

public class CustomerRepository : ICustomerRepository
{
    ICustomerFactory factory = null;

    public CustomerRepository() : this(new CustomerFactory() { }

    public CustomerRepository(ICustomerFactory factory) {
        this.factory = factory;
    }      

    public Customer Find(int customerID)
    {
        // data access stuff here
        return factory.Build(ds.Tables[0].Rows[0]);
    }
}


My concern here is that I'm violating YAGNI because I know with 99% certainty that there is never going to be a reason to give anything other than a concrete CustomerFactory to this repository; since we don't have unit tests I don't need a MockCustomerFactory or similar things, and having so many interfaces might confuse my co-workers.  On the other hand, using a concrete implementation of the factory seems like a design smell.

Is there a good way to come to a compromise between proper software design and not overarchitecting the solution?  I'm questioning if I need to have all of the "single implemenation interfaces" or if I could sacrifice a bit of good design and just have, for example, the base interface and then the single concrete, and not worry about programming to the interface if the implementation is that will ever be used.


  Is there a good way to come to a compromise between proper software design and not overarchitecting the solution? 


YAGNI.  


  I could sacrifice a bit of good design


False assumption.


  and the base interface and then the single concrete,


That's not a "sacrifice".  That is good design.
