Skip to content
caibirdme edited this page May 11, 2018 · 3 revisions

Welcome to the Gendry wiki!

English|中文

Why We Develop Gendry

To achieve high efficiency and maintainability in Go project, there are three simple suggestions:

  • Use standard library if possible
  • Use high quality library on github if needed
  • Add new feature to currently used library rather than developing a new one

In practice, however, currently available libraries are not ideal enough to meet our requirements. Therefore we come up with the idea to design a new library which is effective and efficient, aiming to ease your burden of programing when operating database.

Disadvantages of available libraries are analyzed and listed below:

Flaws in ORM

Though libraries like GORM and beego are widely used, ORM has its obviously flaws. A high level of encapsulation provides semantic APIs helping build sqls, which is very object-oriented but often confusing, resulting in users’ unawareness of roles of API such as Save,HasOne really do. Moreover, database would become the bottleneck with the development of one system, being unstable under increasingly great pressure. Taking the above factors in to consideration, optimization to sql is always needed. However, there are some difficulties in optimization. First, it is hard for new users due to abstract conceptions ORM provide. In fact, by manually optimizing sql, its Object-oriented properties be broken. Second, it is tedious and tiring to learn concepts by browsing detailed documents before using a library, especially for me. There's a detailed blog about flaws in ORM and Here's a heated discussion about whether or not to use ORM.

SQL Builder

Except ORM, sql builders are taken into account so we investigated some high-quality libraries on github. The criteria(defined by me) of high-quality library on github include:

  • A lot of stars
  • Abundant closed issues
  • Full test coverage

Actually a high star count couldnt' insure the quality of a library but to some degree it indicates the practicability, utility and stablility. In the year 2016, when we first get started, the quantity and quantity of related libraries were less compared with today. Most of those libraries are invasive, which is the most significant difference between Gendry and them. Namely, Those libraries not only forge sqls but also execute sqls which require holding the *sql.DB object. You will get stuck if you want to do something while the library doesn't provide such an API and you can't access the *sql.DB object directly. One reason among why those libaries don't make a good choice is that: They provide too many APIs. For many, abundant APIs may not seem as a problem but in our prospective, it is.Though more APIs always means more functionalities, it also brings more complexity. People is preferable to spend their time learning about standard library rather than a related third party library. Third party libraries may vary in projects and most of them will get obsolete soon(front-end developer may more likely to be aware of this).Too many APIs makes their role unclear and the same problem occurs when people can't access *sql.DB directly. In Didi, our database systems are always under much pressure and sqls have to be used very cautiously, lose control of *sql.DD is unacceptable.

Among SQL builders on github, dotsql is relatively an ideal one. It decouples the codes and sqls, so it's very convenient for DBA to review, which can make sqls safer and more efficient.Completely decoupling sqls and codes are widely used in JAVA and C++ projects, but it also has several disadvantages, one of them is ,according to dotsql, when people should use an alias to specify a sql and then fill the placeholders in the sql. However when the sql contains a lot of placeholders, say 6 or even more, it's hard for programmer to remember which placehold is filled by which varaible. And for queries like where in, in many cases it's unpredictable how many placeholders there would be. Actually it often depends on the result lastest query. Handling where in query specifically may work but when considering that Go doesn't support syntax like Query(db, "alias", var1, var2..., var2), we give it up.

Pure SQL

in a previous discussion, many of my colleagues supported pure sql. It's convenient for DBA to review and easy to optimize manually. But pure sql means you need write every sql that would be used. Whenever adding or abandoning a select field you need to write a new sql no matter if they share the same where segment, which means you would repeat yourself over and over. Don't repeat yourself is a key principle in software engineering.

Generally, an ideal sql builder is supposed to be:

  • Simple. Providing users with few concepts and enough samples
  • Noninvasive. Generating parameters for standard API only
  • Powerful. Covering as much cases as possible within the scopre of resposibility

Twenty-eight law is the impulsion of the encapsulation. In most cases some parameters of an API are not needed, and in some cases special handling is not needed either. Therefore by encapsulating a high level API, we can simpify some difficulties. And on those rare occasions we can easily abandon the encapsulation and use more primitive API directly. For example,  Client of net/http in standard library is considered inconvenient by many. Each time before sending a request we have to fill a Request structure which contains a huge amount of fields,which adding extra burden for us. But because it belongs to standard library, which means it is a part of the Go language, it must support any kind of use case. For us, in most cases we don't need set complex headers or hijacker so we can simply use the Get or PostForm in net/http or encapsulate our owns if needed.

There can be some trade off between Avoid complex encapsulation and Don't repeat yourself

If an API is too strong, which always needs more parameters to control its behavior. And very often people don't have that much variables to fill those parameters. It'll make people puzzled. Considering the same complexity, people would prefer the standard library rather than a third party library. So I think it's completely unnecessary to develop a complex library with excessively needless functions. After all, the first two principles of the Unix Philosophy are:

Small Is Beautiful
Do One Thing And Do It Well

A qualified library should use the least API and parameters to cover as much common scenarios as possible.

Apparently, it was quite tricky to make a choice. On one hand highly encapsulated ORM was unwanted, on the other currently(at that time) available sql builders are either too complex or overcoupling. Therefore we believed it’s more acceptable to design a new sql builder according to our demands.

In summary, Gendry has already extensively applied in projects in our company and proved to be stable. Though it's a tiny library, it is our sincere hope that it would simplify your work and ease your burden.

Clone this wiki locally