3 ms·
Dependencies should be treated like if it was your own code. After you have replaced some API for the third time you can start thinking about wrapping it.
by z3t4 8y ago
Dependencies should be treated like if it was your own code. After you have replaced some API for the third time you can start thinking about wrapping it.
- drawkbox 8y agoOr if you start with multiple wrapped dependencies from the start, the library is frequently updated and/or you touch the library in many places in your code across multiple projects especially, those are good places for wrappers/facades/adapters. An example would be in games when you submit an achievement or leaderboard score to a third party such as Apple GameCenter, Google Play Game Services, or other systems like Amazon Game Circle, web or custom. These libraries are frequently updated, they change per platform and you will touch them many places in the codebase, so wrapping them in a progression/statistics/achievements wrapper/facade/adapter is smart from the start.
- z3t4 8y agoEven if you have wrapped it you still have to update your code when there are breaking changes. If you follow "don't repeat yourself" (DRY) there will not really be more work updating, compared to if you had wrapped it. (You should however not follow DRY slavishly - but that is a discussion on it's own.)
- drawkbox 8y agoIf the wrapper/library is generic enough then it can be less work across projects and codebase and won't need to change with an actively updated library that is wrapped. If the abstraction wrapper is tightly coupled, uses third party library types that can change or leaky then yeah, the effort is moot and you end up with more work. Another case is where you have some sort of messaging system where you want responses/events to be uniform to your system rather than unique to a platform or even a company/product that doesn't match your codebase. An example might be wrapping a game recording library, audio library or something that does not fit well in the codebase or complicates maintenance, even stylistically/standards, or you only need small part of the library like activating it, common types messaging or data level. Game engines themselves are massive wrappers around many wrapped systems.
- deleted 8y ago[deleted]
- jstimpfle 8y ago> Dependencies should be treated like if it was your own code Only a Node.js developer could say that. Maybe it's true when the dependency is left-pad or something. Experienced developers in other languages will acknowledge that (non-trivial) code that is not your own code, is not your own code. You seldom have a very good understanding of the underlying models, and the library has absolutely no understanding of your own model. And it's very hard to make a change in code that is not your own. Case in point, I just read the title "Linux fsync() issue..." on the HN frontpage. If you have a large project, say a database, I can only hope that you properly abstracted your synchronization model.
- z3t4 8y agoIf you find an issue in a dependency it's better to fix the dependency, assuming it's open source, rather then wrapping it. Then everyone using it will profit, and don't have to write wrappers. You can abstract the platform layer. It's a lot of work, but might be less work then maintaining a code-base for each platform. If you are working with a very low level API it might be a good idea to abstract it though. You always want to go up one abstraction level, not abstract "sideways". And be aware of the trade-offs like performance, and also being able to understand the code. for example: Developers might know the low level API because it's common knowledge, if you then have made a (leaky) abstraction it might make it much harder to understand.
- jstimpfle 8y agoYou cannot fix the dependency. It's not broken. Libraries are not designed just for your application. That's the point of libraries. And that's why you need a thin layer that translates from the library's less concrete and more complex model to your application's more concrete and less complex model. > You always want to go up one abstraction level I don't think there is such a thing as "abstraction levels". As it says in the Dijkstra quote, abstractions are semantic models. Interfacing means translating between models. Translations between abstractions might or might not be fully realizable. Very often there's a mismatch and the translation is not possible perfectly, in which case it's a leaky translation. And that's ok. Often the only way to deal with reality is to ignore some difficult parts of it, since otherwise the project couldn't be completed. For example, RPC is an abstraction for network requests to be modelled as function calls. This ignores the reality of the unreliability, throughput, and latency, of real world networks. And that's ok. There might be some situations in which the program does not work in the real world. But mathematically speaking, at least the program is correct (in a very obvious way) with regards to the simpler model which, unrealistically, assumes that RPC works just like function calls. So, RPC is not an abstraction that is somehow built on top of network infrastructure abstractions. It's only typically translated to the semantic world of networks. That's an important difference.