''Date your abstractions, don't marry them'' I agree that there is a lot of tediousness in typical SQL, HTML, and CrudScreen usage, but I tend to focus on smaller-scale frameworks for dealing with those rather than strive for The Ultimate Generic Wrapper. This is because the "wrappability" of SQL and string-based protocols varies widely. Thus, I don't even strive to wrap everything any more. I have been burned too many times by the EightyTwentyRule and LeakyAbstraction''''''s. Using helpers gives me the abstraction/simplification where it works, but allows me to abandon it where it does not. I am then not married to one or the other. It is true that I don't completely hide from the "string-ness", but at least I hide from the common repetition. I have yet to see a good pure wrapper from anybody else either, not just me. Thus, the failure of pure wrappers is probably due to it being a nearly impossible goal, an unrealistic abstraction idealism. For example, for insert or update queries, I sometimes put the name-value pairs in a map (associative) array, and then have a utility function to turn that map into SQL clauses. The problem is knowing the field types in order to know when to include SQL quotes and/or how to validate the values. Maps only have two "columns", so one has to store field-type info somewhere else or create nested messes. The ideal would be a data dictionary table, but most languages sadly don't easily support these. Thus, a compromise is to use a function such as: addClause("ssn", ssn, CHAR) or perhaps: addCharClause("ssn", ssn) [The PHP world solved this problem a while ago, by using the dynamic type of the value passed in. See PEAR DB's autoInsert and autoUpdate functions. I almost never write raw INSERT or UPDATE queries any more. -- JonathanTang] * Dynamic type? Many don't use explicit types in PHP or can't rely on them always coming out how one expects. Plus, the DB's type and the PHP type may not match well. I find it better to tell the API how to treat it in SQL. Another thing is that one can combine such type/format checking with validation in general so that SQL creation and validation can be combined. This is why roll-your-own mini-API's may be better: it kills two birds with one stone. Each shop or app tends to have a certain flavor of validation "types" and conventions. ''where's the string, don't over simplify your example while bloating the OOP one, that's dishonest.'' * It is a "regional" (module-level) variable, and thus does not have to be passed in as a parameter. If you want to add it as a parameter or object in your version, be my guest. Related: ResponsibilityDrivenDesignConflictsWithYagni. This appends the key-value pair to an SQL string clause. Typical usage would be in an Update, Insert, or query-by-example screen. OOP fans might complain the string(s) being appended to are not "encapsulated" in an object. However, I have never had to append to more than one SQL statement at a time, and so don't see a need. Thus, I keep the syntax simple. If by chance I later needed such a feature, then I could add a "handle" of some type: addClause(myClause, "ssn", ssn, CHAR) But, if you want or must use OOP, then you can have something simple like this: myUpdate''''''Clause = new Update''''''Clause().addClause("ssn", ssn, Sql''''''Types.Char) Or perhaps: myUpdateClause.addCharClause("ssn", ssn) However, that is more tedious than what we are trying to fix. ''Doesn't look more tedious to me, looks quite simple, and far safer than appending strings since an OOP version would likely build a syntax tree from it than can be cleanly turned into paramaterized sql automatically.'' * Please clarify By using "lite" wrappers for SQL parts, one can still use more powerful SQL structures and features. I am not forced into an all-or-nothing decision about whether to use raw SQL or a wrapper. I use both as needed. I wrap the easy-to-wrap aspects of SQL and leave the rest alone. The wrappers help the repetitive parts without prohibiting fancier SQL usage. They are just that: helpers. ''Strawman, you keep assuming that the OOP versions are somehow less capable than your wrappers, they aren't. OOP query interfaces don't stop you from writing sql when you need to and don't in any way prohibit you from writing fancy Sql, please stop spreading FUD, as someone who admitedly never uses OOP techniques or query interfaces, you are in no position to critique them.'' * This is more about how to create wrappers than it is about OOP versus functions. By the way, what is a "query interface"? ''A query interface is a wrapper for the most common cases, just like yours. To show an example from one of Fowler's books in a statically typed language...'' Query query = new Query(Person.Class).addCriteria(Critera.greaterThan("numberOfDependants",numDependants)); ''Quite flexible, generic, takes care of the common cases, and with the exception of the column name, compiler checked.'' I find those verbose. See ExpressionApiComplaints. ''No more verbose than your method.'' string myClause = "Select * from Person"; addGreaterClause(myClause, "numberOfDependants", numDependants, NUM) If your goal is to completely hide from SQL because you think it is ugly or evil, well, you are on your own. There have been a lot of creative attempts to wrap SQL completely behind imperative API's, but the cure was worse than the desease in every case I saw. I don't think that can happen until SQL is replaced by a better relational language. The API's I've shown are generally to simplify the '''repetitious parts of SQL, not all of SQL'''. INSERT and UPDATE statements are the primary example, but can also help with QueryByExample. The main goal is to reduce repetition, not change one language into another. [For typesafe SQL statement generation, see also TypeSafeJdbcWrapper.] ''Well, Ruby's ActiveRecord implementation, while it can be a pain on some rare occasions (especially when deviating from its conventions), does the abstraction fairly well. Not as versed in Java to know, but .NET on the other hand is, while better than the Vanilla, still a pain in the ass. I would be skeptic of reasons to implement a custom, from scratch wrapper for mainstream languages.'' -- LeoBighetti * I am not sure ActiveRecord qualifies as a "helper". A helper needs these features: ** Another framework or application is not "married" to it. You could do without it without major headache. I could be wrong, but too much of R-on-R seems to assume Active Record. ** Can easily alter the code for a different app that may have different needs. A.R. seems to be a large blob of code in order to be generic and handle all kinds of contingencies. One-size-fits-all is anti-helper. Nor would I create a function/method for every operator (">", ">=", "<", etc.) if I even bothered to wrap those to begin with. I would just have it as a parameter. They are more visual so we might as well use them (see LispLacksVisualCues). -- top ''OOP let's you create any relational language you like, and use it natively in your language, it can be translated to Sql under the hood and on the fly. Why wait for something better when you can have it now?'' I would enjoy an example. ''See TutorialDee. A language, any language, is just an abstract syntax tree, and can easily be represented by objects, which do trees very well, thus you can make up any language you like, and use it, instead of Sql.'' Well, turning expressions or languages into API's is not something I am fond of, as described in ExpressionApiComplaints. But, I am talking about using SQL-based RDBMS here. I agree that SQL has messy syntax, and have even proposed my own relational language under TopsQueryLanguage, but SQL is not going away anytime soon. It is the QWERTY and COBOL of relational query languages. But even TutorialDee or TopsQueryLanguage is far more readable as strings than as expression API's, at least to me. I think most developers would agree with me. But, this is probably a topic to be moved or finished in ExpressionApiComplaints. ---- '''HTML Example''' A common pattern in web-forms (CrudScreen''''''s) is a bunch of input fields of the form: Name: [ ] Date: [ ] format mm/dd/yyy Category: [(select category) |v] // meant to be a drop-down list .... I used to try to make a generic API for such, but found it suffers from problems of pure wrappers described above. Thus instead I use helper functions that "sandwich" the HTML form elements. formHeading("My Sample Form", formName) rowStart("Name") rowEnd() rowStart("Date") rowEnd("format mm/dd/yyyy") rowStart("Category")