Developer Code
Within UCE, we use several programming languages, including Java and Python, as well as multiple databases, each with its own query language, such as SQL and SPARQL. The core application, however, is written in Java, and thus the primary focus of development is on Java.
Any developer who wishes to contribute to UCE should read the Code of (Development) Conduct.
Also, feel free to ⭐ the repo and join our Discord server to engage with the other developers and users of UCE.
1. Git Management
Fork the UCE repository. Development is carried out on the develop
branch. For larger features or features that affect multiple parts of the codebase, consider creating a dedicated feature branch. However, in general, avoid creating separate branches for every minor feature. All changes must be submitted via a pull request.
No-break Policy
Your changes should never break the application for others in any way! Also check your (local) configurations!
2. UCE is Generic but Flexible
UCE is not a tool designed for a single specific use case or application. Therefore, when developing UCE, always consider how other domains, projects, and use cases might benefit from your contribution.
Additionally, if your feature relies on situational conditions—such as specific annotations or user configurations—UCE must still function properly even when your feature is not active or cannot operate due to missing requirements. UCE must always adapt flexibly to the user's environment and configuration.
3. Keep it Simple
This isn't rocket science. There’s no benefit in abstracting a triangle into a geometric shape, then into a shape, then into a unit, then into an object, and finally into an accumulation of atoms. Keep it simple—abstract only when necessary. Code redundancy should be avoided, but it's not a plague. Don’t overthink it too much. No one wants to traverse through 10 methods just to finally reach the actual logic.
4. No Hardcoded SQL
Well, at least wherever applicable. We use Hibernate as an ORM within UCE, which should make writing hardcoded queries obsolete. For longer and more complex procedures, use PostgreSQL’s stored procedures.
However, in certain situations, you may encounter raw SQL strings in the source code—for example, for dynamic interpolation or other necessities (I'm sure the comments will provide detailed reasoning ;-). As a rule of thumb: avoid hardcoding whenever possible (this guideline does not apply to SPARQL queries).
For the creation of indexes, triggers, and similar database elements, you’ll find a database
folder within the repository. Place your SQL scripts there—they will be executed automatically when UCE starts.
5. To var
or not to var
For now, we’ve agreed to leave this up to you. Personally, I find writing out longer types in Java annoying and hard to read (looking at you ArrayList<ArrayList<Tuple<String, Integer>>>
), but rules like "use var
when the type is easy, otherwise write it out" just make you overthink things that really aren’t important.
Do as you like (for now).
6. AI
You can use whatever tools or sources you prefer for development—just make sure that, if a source needs to be cited, you cite it appropriately. Also, double-check any AI-generated code and adapt it to match the style and structure of our existing codebase.
Be sure to delete useless comments often generated by AI models, like:
Comments like these show poor form and clutter the codebase with unnecessary noise. But, talking about comments...
7. Comments
Every Programmer
“My methods don’t need comments, they speak for themselves.”
No, they don't speak for themselves and yes, they need comments. Write small, precise, and concise comments that explain the flow of the code.
However, don’t overdo the Javadoc. If a private class is 2,000 lines long and 1,600 of those are comments, you’re doing something wrong.
8. Spring Framework
UCE is built using the Spring framework and Maven. As such, we use Dependency Injection with services.
These services are to be created in the uce.common
submodule, then registered in SpringConfig.java
for DI, and should encapsulate all logic related to their specific functionality. For example, you will never find a request to our PostgreSQL database outside of the designated database service (as always, with exceptions).
For those who haven’t worked with these patterns or frameworks before: familiarize yourself with the codebase and replicate the patterns from already existing services, logic classes, and other components.
9. Models are Models
Complementing point 8, we oppose the idea of coupling logic with models. E.g., each of the data classes associated with Hibernate—and thus the database—are purely data models, akin to structs. Through services, we fetch, modify, transform and save them.
So remember:
- Logic belongs in services.
- (Persistent) Data belongs in models.
- Everything in between is utility, configs, routes or special cases.
Keep them separated.
10. Have Fun
This list sounds much stricter than it actually is, and it might give the impression that UCE was developed perfectly following these rules—which it wasn’t. We all work under time pressure, make mistakes, learn over time, write "TODO: cleanup later", and then never get around to cleaning it up.
So take this as a guideline—something to strive for—but remember: then the actual coding happens.