Solving database abstraction brainfart

blov · · 471 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I went for a walk and it was (or still is) a rainy sunday with not much to focus on. Since I recently went and created a storage interface and kept it as abstract or neutral as possible, also the implementations...</p> <p>But first things first.</p> <p>The problem is creating a database abstraction &#34;layer&#34;. There&#39;s .. this one library .. that was just posted recently, version 3 now... fml up..something. It doesn&#39;t really solve the problem.</p> <p>I want a model that behaves the same way for every database used, without needing to write special implementations for each database.</p> <p>So I started creating a modelinterface, like HouseModelInterface AnimalModelInterface etc. and storageinteraces like HouseStorageInterface, AnimalStorageInterface. And you end up writing a type MongoDBHouseStorage struct{} and type PostgreSQLHouseStorage struct{}. And HouseService implementing higher level functionality (as in DDD repositories). And it works but it is a lot to type. Lots of working around the problem that generic models can&#39;t be done in Go (at least not without significant man hours overhead).</p> <p>Or can they? What is the actual difference between a mongodb and a *sql model? *sql usually has an ID that is an integer. mongodb usually has an ID that is a bson.ObjectID. toMany toOne are handled more or less the same way.</p> <p>type Data struct { ID string Comments []string // or []int, or []Comment } type Comment struct{ DataID string // or int }</p> <p>In my first attempt I added GetID() string and SetID(string) methods because you can itoa and atoi and you can bson.ObjectID().Hex() and bson.ObjectIDHex(id string). Lowest common denominator.</p> <p>But is the string primitive really the lowest common denominator? Why does it have to be a builtin? Why not create your own lowest common denominator? Your custom field type. dbal.ID</p> <p>type DataModel struct { ID dbal.ID <code>bson:&#34;_id,omitempty&#34; gorp:&#34;id,autoincrement&#34; json:&#34;id&#34;</code> }</p> <p>You can get an int out of it, a string(e.g. slug, UUID) a bson.ObjectID. mgo has Getter and Setter interfaces. It would work with Mongo. Does &lt;your favorite &#34;orm&#34;&gt; (pgsql hipsters, gorp? gorm?) have that kind of interfaces? If yes, problem solved.</p> <p>dbal.ID being a generic data type, even polymorphic if you will Instead or working around the problem you tackle the root of it.</p> <p>A toMany and toOne should be pretty simple</p> <p>type ToMany struct { Type interface{} IDs []dbal.ID }</p> <p>type DataModel struct { ID dbal.ID Comments ToMany{Type:model.Comment{}, IDs: ...} }</p> <p>type ToOne struct { ID dbal.ID }</p> <hr/>**评论:**<br/><br/>shovelpost: <pre><blockquote> <p>I want a model that behaves the same way for every database used, without needing to write special implementations for each database.</p> </blockquote> <p>And I want 1 million dollars.</p> <p>There is no way to write an abstraction like that without ending with something incredibly complicated and/or horribly ugly (reflection).</p> <p>But you could always use the power of code generation to generate something for your particular case: <a href="https://github.com/vattle/sqlboiler" rel="nofollow">https://github.com/vattle/sqlboiler</a></p> <blockquote> <p>But is the string primitive really the lowest common denominator? Why does it have to be a builtin? Why not create your own lowest common denominator? Your custom field type. dbal.ID</p> </blockquote> <p>Go is a pragmatic language. Write your interface, write the implementations that you need and go to the next problem. If you want abstractions like the ones you are describing you should try Ruby instead.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

471 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传