Q:

in java how do i design an api to be both generic, simple, readable

My example is this I want my user to call
findCustomers(...)

now my question is about the argument to this method.
I have a
Customer.java

object and I would like the user to be able to use the library to search by customer name, and customer id.
now i would not want to create multiple methods
findCustomerById(String id)
findCustomerByName(String name)
findAllCustomers()

Instead what I thought of doing is this a generic findCustomer
/** if you pass only custoer.name and rest of fields are null will search by name,
if you pass a null custoer object will return all customers, if you pass both custoer id and his name will search by both fields). **/
findCustomer(Customer customer)

Now I have a generic single method for api but i don't like that i pass nulls in an object, i don't like nulls.
anyone has a clear cut best practice for such an api?
thanks

A:

how about something like a fluid api for queries:
List<Customer> matches = find(new CustomerQuery().withName("john(.*)").withId(42));

A:

What you are trying to build is called Query By Example. It is OK, but it has limitations: your Customer class is re-purposed for being a query parameter, rendering some of its code useless or counterproductive. For example, if you add a validation requiring the name to contain only letters, you would not be able to query for names with wildcards.
One approach to address this is to provide a query builder class designed specifically to handle query parameters. The query object itself could wrap a Map<String,Object> of parameter bindings passed by the user, letting your query API take it apart and pass the corresponding data to a query of the underlying data store.
QueryObject<Customer> qObj = new QueryObject(Customer.class);
qObj.setParameter("FirstName", "Joe");
qObj.setParameter("LastName", "S*");
qObj.setParameter("ID", 123);
List<Customer> cust = findCustomers(qObj);

