Our codebase has ~250 services written in a mix of Java (primarily), Go, JS (using Closure Tools), and I was interested in views on how to best organize it for the purpose of migrating to Bazel, enabling sharing, and controlling dependencies.
Presently we have something like this:
//src/com/corp/$service/... # Java service client and server, ad-hoc organization
//src/com/corp/$service/app/views/... # Closure templates
//src/com/corp/common/... # application-agnostic libraries
//js/... # js code + tests, built using plovr
//gocode/src/corp/... # go code + tests, built using the go tool
Our Java code is built using a custom tool that symlinks relevant Java files into a build tree and runs ant / javac on the whole thing.
Questions:
- It seems like the right organization for a Java service package is to have a clear separation between RPC Client / Client library & the service implementation. Any particular naming conventions? What does Google use?
- What are good guidelines for services' public interface being allowed to depend upon other services? In particular, this happens for us when a service uses protocol buffers defined by another (e.g. there are a bunch of services that operate on the same proto data structure). Is this a possible source of cyclic dependencies?
- Are there any tips for taking a Java codebase and migrating it to bazel / removing cyclic dependencies? The best thing I've come up with is to use dependency visualization tools and Eclipse "Move" refactorings.
- Have people found it to be a good idea to have a single tree of templates to aid sharing between applications and making goog.require('templatepath') work?
Any thoughts (or links to resources)?
Thank you!
Rob
Our codebase has ~250 services written in a mix of Java (primarily), Go, JS (using Closure Tools), and I was interested in views on how to best organize it for the purpose of migrating to Bazel, enabling sharing, and controlling dependencies.
Our Java code is built using a custom tool that symlinks relevant Java files into a build tree and runs ant / javac on the whole thing.
- It seems like the right organization for a Java service package is to have a clear separation between RPC Client / Client library & the service implementation. Any particular naming conventions? What does Google use?
- What are good guidelines for services' public interface being allowed to depend upon other services? In particular, this happens for us when a service uses protocol buffers defined by another (e.g. there are a bunch of services that operate on the same proto data structure). Is this a possible source of cyclic dependencies?
- Are there any tips for taking a Java codebase and migrating it to bazel / removing cyclic dependencies? The best thing I've come up with is to use dependency visualization tools and Eclipse "Move" refactorings.
- Have people found it to be a good idea to have a single tree of templates to aid sharing between applications and making goog.require('templatepath') work?
Google uses a little bit of a different directory structure internally. For example, pretty much all .java files are under //java/com/google, //javatests/com/google, and //third_party/java_src for open source projects that have things like Maven directory structures. //javatests has a special meaning in Bazel, where all rules are testonly=True by default. //third_party also has a special meaning, where licence declarations are required.
import "third_party/cloud/kubernetes/pkg/api/resource/resource" // "k8s.io/kubernetes/pkg/api/resource"
Our majority case is all-java services communicating with protobufs. We are not using gRPC, due to everything being on proto2. (It sounded like there was no upgrade path, and we didn't want to be stuck using a mix of proto2 and proto3 forever)
[[ -z "$(bazel query 'somepath(//java/com/yext/service/client/...,//java/com/yext/service/server/...)')" ]][[ -z "$(bazel query 'somepath(//java/com/yext/service/server/...,//java/com/yext/service/client/...)')" ]]
To clarify, is it common to have a mix of private and public code in the same java package along with separate BUILD rules, or is //java/com/google/doodle/*.java public and //java/com/google/doodle/impl/**/*.java private? (Assuming that doodle is a java service) Or do most packages follow the "1:1:1 rule"?
How do you organize javascript and javascript tests?
Interesting! So you find that you can often avoid refactoring code when porting by writing the right rules? I didn't really consider that approach (I was following 1:1:1)
Do you mind providing an example? If doodle service has templates to be shared with registrar service as well as with javascript, where would you put them? Leave them wherever they were initially used/added and reference them from the subsequent spots using BUILD rules?
--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/60dbfa8b-de3a-4bb8-99f4-7eebf1dfaec4%40googlegroups.com.