Best way to have proto folder for multiple platform - grpc

What is the best practice to hold proto folder for multiple platform, such as backend, iOS, Android, and Web?
I came up with 3 ideas. Which one would be the best? Do you know better ideas than them?
1st: Should I have all in 1 repository including proto folder?
2nd: Should I split all like proto repo, iOS repo, backend repo etc, and share proto folder as a git submodule?
3rd: Should I make independent proto folder for all repos?

My recommendation is that you use one repository for your proto files and use something like git submodules to include it in other repositories. The reasons are the following:
Proto files generally change way less often than your code, so low overhead when using git submodules (no need to git pull all the time).
It prevents having different versions of your proto files which can lead to unexpected behaviours when field tags are mismatching.
Modularity. If later you decided to do another project (eg: Desktop app) with the same proto files, you would just add a submodule, not copy everything and make specific changes to your project.
Furthermore, proto files are design to be shared across different language by being able to add options for specific languages. If you use this submodule in a iOS project and generate code for Swift only the options for Swift will be taken into account, same for Kotlin/Java and same for JS.
Even though I believe this is the safest way to manage your proto files, that's only my recommendation. Different use cases might need different architecture.

Related

serverside-rendering react app with code splitting using loadable-components

I recently implemented serverside-rendering react app with code splitting using loadable-components
But it seems that loadable-components itself dependent on webpack, since loadable replaces jsonp_callback with its own reporter.
So what are the alternative options that we can use when using other bundlers like rollup, esbuild?
Do we have to manually walk through the react tree to pre configure which chunk is needed on which component unless there is no specific bundler targeted library like loadable-components when implementing code splitting on serverside rendering?
Is tsconfig typeRoots unnecessary?
First, let us consult the compiler options reference:
The documentation for typeRoots states (emphasis mine):
By default all visible #types packages are included in your compilation. Packages in node_modules/#types of any enclosing folder are considered visible. For example, that means packages within ./node_modules/#types/, ../node_modules/#types/, ../../node_modules/#types/, and so on.
If typeRoots is specified, only packages under typeRoots will be included.
That second line is important: if you don't set typeRoots then tsc defaults to looking for directories under node_modules containing #types in their directory names.
(The documentation doesn't say if it chooses node_modules because of the moduleResolution parameter though. (I suspect I'd need to dig-in tsc's source-code to find out for sure).)
If you do set a value for typeRoots than that overrides tsc's node_modules/**/#types* lookup logic and it will then only look in the specified directories.
As I know, I have to specify the path of the above file into typeRoots option of tsconfig file since typeRoots defaults to look into the node_modules/#types.
Not necessarily. You could also add your extra typings files' locations to the paths parameter and leave the typeRoots parameter blank/un-set, which means tsc will retain the "node_modules/#types-and-ancestor-walking behavior" but will see your .d.ts files just fine.
This scenario is mentioned in this TypeScript GitHub thread: https://github.com/microsoft/TypeScript/issues/13581
So if you're asking about your specific local environment on your machine: and assuming that you're sticking with the normative, typical (I dare say mainstream) TypeScript working idioms (such as using npm) then yes: you can remove the typeRoots parameter because tsc's (current) default behavior is to look for node_modules directories in the same location as your tsconfig.json.
(I understand that VS Code might also be pulling some strings behind-the-scenes to make tsc "aware" of your project files and dependencies and for its language-server process - but that shouldn't matter as you'll notice tsc should work identically from the command-line outside of VS Code).
If you're asking about the fundamental necessity of the typeRoots compiler option, and supposing that you're thinking "that because practically everyone is using npm and node_modules then why is the TypeScript team spending their time supporting unusual development configurations?"_ - well, for many very good reasons: tools shouldn't be dependent on other tools controlled by third-parties1: Consider the possibility that the npm ecosystem and/or NodeJS software could fall out of fashion overnight and then we'd be stuck with tsc's defaults still using node_modules when everyone is rockin' some new cool JS environment: there'd be headaches for many years to resolve the mess (not that the JS ecosystem isn't a mess as it is).
And there are many good reasons to not use npm and node_modules: people could be using TypeScript in an environment without internet access (think: secure software development, the defence industry, national secrets, etc) - those people in those situations might have a network share full of approved or known-trustworthy libraries that won't be using node_modules's naming convention - in which case if those people want to use d.ts files they'll need to manually configure the typeRoots parameter for themselves.
1 I'm aware that npm (which is legally separate from NodeJS, btw) is maintained by npm Inc, which is a subsidary of Microsoft (by way of being acquired by GitHub, also a Microsoft property), so having tsc depend on npm shouldn't be a problem - but that's a very recent thing: Microsoft only acquired npm 18 months ago in March 2020 - and Microsoft could very well spin-off npm Inc - or run it into the ground and everyone switches to yarn. So regardless of the end legal owners of whatever tooling is currently popular, you don't want unnecessary dependencies like that.

Artifactory - Concept of File Versions

I'm currently starting with JFrog Artifactory. Up to now I have only been working with source code control systems not with binary repositories.
Can someone please tell how the versioning of files is done in Artifactory?
I have been trying to deploy a file, then change it and deploy it again.
The checksum has changed, so it's the new file. But it seems that the old version is gone.
So it looks like there are no version of files. If I want that do I have to do it in the filename?
I found versions related to packages.
But I was thinking to use it for other files as well.
Thanks for your help
Christoph
Artifactory, unlike a VCS system, is not managing a history of versions for a given path. When you deploy an artifacts over an existing artifact, it will overwrite it (you can block this by configuring the right permissions).
If you wish to manage permission for generic artifacts (ones which are not managed by a known package manager like npm, Maven etc.), there are a couple of options you can take:
Add the version as part of the artifact name, for example foo-1.0.0.zip
Add the version as part of the artifact path, for example /foo/1.0.0/foo.zip
Combine the 2 above approaches, for example /foo/1.0.0/foo-1.0.0.zip
Use an existing package management tool which is flexible enough to handle generic packages. Many people are using Maven to manage all types of packages beyond Java ones (it comes with its pros and cons)
From the Artifactory point of view there are a couple of capabilities you can leverage:
Generic repositories - aimed at managing proprietary packages which are not managed by a known package manager
Custom repository layout - can be used to define a custom layout for your generic repository and assist with tasks like automatic snapshot version cleanup
Properties - can be used to add version (and other) metadata to your artifacts which can used for searching, querying,resolution and more
Lastly, Conan is another option you should consider. Conan is a package manager intended for C and C++ packages. It is natively supported in Artifactory and can give you a more complete solution for managing your C libraries.

designing large projects in OCaml [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
What is a best practices to write large software projects in OCaml?
How do you structure your projects?
What features of OCaml should and should not be used to simplify code management? Exceptions? First-class modules? GADTs? Object types?
Build system? Testing framework? Library stack?
I found great recommendations for haskell and I think it would be good to have something similar for OCaml.
I am going to answer for a medium-sized project in the conditions that I am familiar with, that is between 100K and 1M lines of source code and up to 10 developers. This is what we are using now, for a project started two months ago in August 2013.
Build system and code organization:
one source-able shell script defines PATH and other variables for our project
one .ocamlinit file at the root of our project loads a bunch of libraries when starting a toplevel session
omake, which is fast (with -j option for parallel builds); but we avoid making crazy custom omake plugins
one root Makefile contains all the essential targets (setup, build, test, clean, and more)
one level of subdirectories, not two
most subdirectories build into an OCaml library
some subdirectories contain other things (setup, scripts, etc.)
OCAMLPATH contains the root of the project; each library subdirectory produces a META file, making all OCaml parts of the projects accessible from the toplevel using #require.
only one OCaml executable is built for the whole project (saves a lot of linking time; still not sure why)
libraries are installed via a setup script using opam
local opam packages are made for software that it not in the official opam repository
we use an opam switch which is an alias named after our project, avoiding conflicts with other projects on the same machine
Source-code editing:
emacs with opam packages ocp-indent and ocp-index
Source control and management:
we use git and github
all new code is peer-reviewed via github pull requests
tarballs for non-opam non-github libraries are stored in a separate git repository (that can be blown away if history gets too big)
bleeding-edge libraries existing on github are forked into our github account and installed via our own local opam package
Use of OCaml:
OCaml will not compensate for bad programming practices; teaching good taste is beyond the scope of this answer. http://ocaml.org/learn/tutorials/guidelines.html is a good starting point.
OCaml 4.01.0 makes it much easier than before to reuse record field labels and variant constructors (i.e. type t1 = {x:int} type t2 = {x:int;y:int} let t1_of_t2 ({x}:t2) : t1 = {x} now works)
we try to not use camlp4 syntax extensions in our own code
we do not use classes and objects unless mandated by some external library
in theory since OCaml 4.01.0 we should prefer classic variants over polymorphic variants
we use exceptions to indicate errors and let them go through happily until our main server loop catches them and interprets them as "internal error" (default), "bad request", or something else
exceptions such as Exit or Not_found can be used locally when it makes sense, but in module interfaces we prefer to use options.
Libraries, protocols, frameworks:
we use Batteries for all commodity functions that are missing from OCaml's standard library; for the rest we have a "util" library
we use Lwt for asynchronous programming, without the syntax extensions, and the bind operator (>>=) is the only operator that we use (if you have to know, we do reluctantly use camlp4 preprocessing for better exception tracking on bind points).
we use HTTP and JSON to communicate with 3rd-party software and we expect every modern service to provide such APIs
for serving HTTP, we run our own SCGI server (ocaml-scgi) behind nginx
as an HTTP client we use Cohttp
for JSON serialization we use atdgen
"Cloud" services:
we use quite a lot of them as they are usually cheap, easy to interact with, and solve scalability and maintenance problems for us.
Testing:
we have one make/omake target for fast tests and one for slow tests
fast tests are unit tests; each module may provide a "test" function; a test.ml file runs the list of tests
slow tests are those that involve running multiple services; these are crafted specifically for our project, but they cover as much as possible as a production service. Everything runs locally either on Linux or MacOS, except for cloud services for which we find ways to not interfere with production.
Setting this all up is quite a bit of work, especially for someone not familiar with OCaml. There is no framework taking care of all that yet, but at least you get the choice of the tools.
OASIS
To add to Pavel answer:
Disclaimer: I am the author of OASIS.
OASIS also has oasis2opam that can help to create OPAM package quickly and oasis2debian to create Debian packages. This is extremly useful if you want to create a 'release' target that automate most of the tasks to upload a package.
OASIS is also shipped with a script called oasis-dist.ml that creates automatically tarball for upload.
Look all this in https://github.com/ocaml.org.
Testing
I use OUnit to do all my tests. This is simple and pretty efficient if you are used to xUnit testing.
Source control/management
Disclaimer: I am the owner/maintainer of forge.ocamlcore.org (aka forge.o.o)
If you want to use git, I recommend to use github. This is really efficient for review.
If you use darcs or subversion, you can create an account on forge.o.o.
In both case having a public mailing list where you send all commit notification is a must have, so that everyone can see them and review them. You can use either Google groups or a mailing list on forge.o.o.
I recommend to have a nice web (github or forge.o.o) page with OCamldoc documentation build everytime you commit. If you have a huge code base this will help you to use the OCamldoc generated documentation right from the beginning (and fix it quickly).
I recommend to create tarballs when you reach a stable stage. Don't just rely on checking out the latest git/svn version. This tip has saved me hours of work in the past. As said by Martin, store all your tarballs in a central place (a git repository is a good idea for that).
This one probably doesn't answer your question completely, but here is my experience regarding build environment:
I really appreciate OASIS. It has a nice set of features, helping not only to build the project, but also to write documentation and support test environment.
Build system
OASIS generates setup.ml file from the specification (_oasis file), which works basically as a building script. It accepts -configure, -build, -test, -distclean flags. I quite used to them while working with different GNU and other projects that usually use Makefiles and I find it convenient that it is possible to use all of them automatically here.
Makefiles. Instead of generating setup.ml, it is also possible to generate Makefile with all options described above available.
Structure
Usually my project that is built by OASIS has at least three directories: src, _build, scripts and tests.
In the former directory all source files are stored in one directory: source (.ml) and interface (.mli) files are stored together. May be if the project is too large, it is worth introducing more subdirectories.
The _build directory is under the influence of OASIS build system. It stores both source and object files there and I like that build files are not interfered with source files, so I can easily delete it in case something goes wrong.
I store multiple shell scripts in the scripts directory. Some of them are for test execution and interface file generation.
All input and output files for tests I store in a separate directory.
Interfaces/Documentation
The use of interface files (.mli) has both advantages and drawbacks for me. It really helps to find type errors, but if you have them, you have to edit them as well when making changes or improvements in your code. Sometimes forgetting this causes nasty errors.
But the main reason why I like interface files is documentation. I use ocamldoc to generate (OASIS supports this feature with -doc flag) html pages with documentation automatically. In my opinion it is enough to write comments describing each function in the interface and not to insert comments in the middle of code. In OCaml functions are usually short and concise and if there is a necessity to insert extra comments there, may be it is better to split the function.
Also be aware of -i flag for ocamlc. The compiler can automatically generate interface file for a module.
Tests
I didn't find a reasonable solution for supporting tests (I would like to have some ocamltest application), that's why I am using my own scripts for executing and verifying use cases. Fortunately, OASIS supports executing custom commands when setup.ml is run with -test flag.
I don't use OASIS for a long time and if anyone knows any other cool features, I would like also to know about them.
Also, it you are not aware of OPAM, it is definitely worth looking at. Without it installing and managing new packages is a nightmare.

Defining 'package' information in component.json and package.json

I'm creating a javascript library that I want make available through Bower to my internal company. I'm using Grunt to build my library.
My issue is that grunt's convention is to use package.json to define dependencies, library versions, dependencies, etc.
Bower, on the other hand, assumes that that same information is found in a component.json file.
What's the intended use of these two? They seem to serve essentially the same purpose. Do I need to create both and cut and paste the shared information?
We've gotten a lot of these kinds of question and everyone assumes we could share a lot metadata between these formats, but the reality is that only the name and version fields are sharable and only the version field changes regularly. If you find it cumbersome having to update two fields when you release something, there are tools out there that can automate this, eg. grunt-bumpx.
package.json is intended for back-end purposes, in this case specify grunt tasks, node dependencies, etc. In the other side, bower.json is intended for front-end purposes.

What folders are commonly used by version control systems?

I need to know what folder names are commonly used by Version Control systems. Many VCSs will create a hidden folder, usually in the top level of the source tree, to store the information that they use.
So far, I only know that Git uses .git/ and SVN uses .svn/.
What are the folder names that other popular VCSs use?
We could probably divide the VCSs into three groups:
Special Subdirectory in each directory
CVS
Subversion (.svn)
The advantage of this is that each directory in the working copy is a self-contained working copy: you can copy it out somewhere else and it will still work. The obvious disadvantage is the clutter. Using automatic tools to scan over one of these working copies need special filtering or they will return spurious results.
Single special directory for each working copy
Mercurial (.hg)
SVK
(Maybe Git, I'm not sure?)
Special file system support
ClearCase (dynamic view is a mounted FS; snapshot view is more similar to the single directory case)
Mercurial = a single .hg directory

Resources