0

We're currently using the Apache Camel Java DSL to structure our application, but I guess this question can mostly apply to any DSL in general.

Now, amongst our developers, we are divided on two polar opinions as to how to structure our codebase:

Approach 1:

Use the DSL as rarely as possible, and stick to using plain Java classes for representing our application logic. Our code is driven by the DSL, so the idea is to delegate the application logic processing (routing, integration logic, etc.) to a Java class as soon as possible, so that the rest of the application logic is completely independent of the DSL.

Pros:

  • Your code is mostly decoupled from the framework. Useful if you want to replace the framework with something else.

Cons:

  • You are not making full use of the DSL, which abstracts out so much boilerplate code for you. You might as well not use the DSL at all in the code, and it would not make any difference.
  • (Specific to Apache Camel) Since the DSL is provided by a framework, the moment you delegate the application logic to a Java class, you cannot use the DSL again within any of the code that is called by the class. So if you want to use a functionality that the DSL provides within a Java class, then you would have to implement it yourself.

Approach 2:

Use the DSL to structure the 'backbone' of our application logic. The actual business logic operations would be defined in modular plain Java methods (i.e Camel processors), which would be called through the DSL.

Pros:

  • You are making full use of the DSL. If you want to execute an operation that the DSL completely abstracts out for you, you can do it without reinventing the wheel.

Cons:

  • Code is tightly coupled to the framework. Tomorrow if you want to replace the framework, you would need to rewrite the application
  • It would take more effort to onboard new developers.

So my question is, based on your experiences, which approach would you all favor in the long run, and why? I don't have a specific criteria on which to evaluate either approaches, we were considering anything that leads to cleaner code and better project maintainability in the long run, as the criteria when discussing amongst ourselves.

11
  • 2
    What functionality does the Camel Java DSL provide that is actually useful in business logic? I can see how it can help with routing and other application concerns, but I don't see what benefits it can bring to business concerns.
    – Rik D
    Commented Nov 3, 2020 at 9:37
  • Okay. I suppose I was using application logic and business logic interchangeably. I have edited my question to reflect it correctly. To clarify, as per approach 2, our core business logic is within several modular processors, and we're using Camel mainly for routing between these processors through a 'backbone' route. But whenever we have the opportunity to make use of a Camel component directly (eg: http4, JPA, etc), we use that directly in the route. Commented Nov 3, 2020 at 10:06
  • That makes the question more clear to me. I'm affraid it might be closed as opinion based, but perhaps someone can think of a good authoritative answer. I would personally lean towards approach 2; if you commit to a framework it's unlikely you'll change it later on, so you might as well use all features it offers (if it makes you more productive).
    – Rik D
    Commented Nov 3, 2020 at 10:16
  • High-level technical decisions like this need to be driven by the business. You're asking whether to invest their money in migrating away from a key piece of technology by rewriting some or all of it in a different language. This decision belongs to whoever controls the technical budget for your team; they will need to look at both the costs and savings (ideally by analysing historical data on how much time/money is typically spent on development, testing, support, maintenance, etc.), compare against how much it might cost to replace all that, and whether it's worthwhile long-term. Commented Nov 3, 2020 at 10:21
  • "processing to a Java class as soon as possible" - processing of what? That's the key issue. If you're talking about business-logic related processing, that should be done by your own code. If you are talking about routing concerns, message translation, and other integration-related shenanigans, that should be done by Camel. If both camps aren't thinking about this separation of concerns, than both camps are wrong. Commented Nov 3, 2020 at 10:52

3 Answers 3

2

Formally your question boils down to: How to choose which programming languages/domain specific languages are used to build an application?

And they answer is: it depends...

  • Knowledge: How easy is it to maintain a development team on this particular mix of languages/frameworks/platforms. Not just developers, but testers, business analysts, and managers. How many people can be hired from market with these skills, how much time does it take to onboard, what retention devices are in place to capture key knowledge for later development?
  • Setup: What are the material costs of those languages? Licensees, support contracts, compilers/interpreters/libraries requiring installation/updating/management, the minimum spec for a computer to work with this software, electricity usage (particularly when considering large deployments), network bandwidth/latency, Installation procedures, etc...
  • Maintenance: How is the system to be maintained? What are the shearing forces on each language/framework/platform: Long-term support, community health and size, upgrade paths, replacement options...
  • Direction: What new requirements is the business likely to request/require? What is their most important priority? How quickly can the system shift footing?
  • Level of Service/Optimisation: How much wriggle room is there in delivering the service? How fast must it be and how easy is it to scale up, scale out, and scale down in response to demand change?

Somewhere in that maze of conflicting requirements is the answer you are looking for.

Generally any application will be constructed from many languages: XML, JSON, Templates of various kinds, database query languages, platform languages (C, Java, C#, LISP, etc...), shell languages (generally for building/deployment).

So there isn't any hard and fast rule about how much and what. Just forces dictated by labour markets, schools, popularity of languages, tool costs, etc...


But I don't think that is your problem. I think your problem is that the team's beliefs are split on the future composition of the system:

  1. It is unmaintainable to adopt this new Language/Framework/Platform, find another way
  2. It is a tech debt to adopt this new Language/Framework/Platform and it needs remediation now/soon.
  3. It is unmaintainable to not adopt this new Language/Framework/Platform and leverage its strength in balance with the existing code base.
  4. It is unmaintainable to not fully embrace this new Language/Framework/Platform and shift away from the previous way of doing things™.

Now it looks like you already have this framework in place and in use. So belief 1 is out. It seems to be a war between belief 2, and belief 3/4.

If you want to go to beliefs 3/4, you will need to convince those holding belief 2 to commit. This may require some forward planning of contingencies for when Apache pulls support for that DSL.

Roughly: Adopt the framework in house (if open source), have substitutions lined up and know which features can be ported.

Alternately it might be a training/cultural issue: not comfortable with camel development, or a belief that it isn't a stable language (compared to java it has some time to go to prove stability).

If you want to go toward belief 2, you will need to convince those with beliefs 3/4 that the risk/maintenance is too high. Again it could be a training issue (not comfortable with java), or a cultural issue (java is ancient), or it could be that the current code base stinks to the high heavens (perhaps cleaning it up?).

Regardless the reason for the divide is what you should be figuring out first. With that knowledge in hand you can figure out what can be done given all the constraints.

There is no guarantee that this can be resolved to every ones satisfaction. But if it is done openly, honestly, and in good faith you maximise the chance that this makes the team stronger.

The alternative is that people on the team will not feel heard, will feel detached, and intentionally or not work against the direction chosen. This can cause the project/company to fail, demoralisation is no joke.

0

From my standpoint, it's like the question of whether to use the standard library data structures or your own in most cases. I work in a domain that develops a boatload of in-house tools.

I always figured if those tools are worth their costs in being tailored to our needs, we absolutely should marry them and make them our wives/husbands. I realize that's a bit contrary to the mainstream opinion preferring what is most widely standard and accepted and it might just be my domain.

But you absolutely need the team to be on the same page here with respect to the tools you use, for any tools you introduce. And even in the intra-language level, that tends to practically include compilers and debuggers and IDEs and so forth along with your architectural design decisions. But in my domain, I cannot understand the external allergy to DSLs, or code generators, or anything of this nature, provided the team is on board. And I don't understand why they aren't when they spend 4 hours working on something that should take 2 minutes if they were just using the right tools. And we simply can't afford for the team not to be on board, since the "standard-approved" tools we use simply require too much time, or inefficiency, for our purposes.

I don't know and I'm sure it ultimately boils down to an "it depends" for "everyone", but in my domain, if we can't commit to the finely-tailored designs and tools we created for our use cases (whether interfaces you designed within your language or tools you built outside), then we're never going to get anywhere. So I'm in favor of using such in-house tools and designs whenever applicable and getting people on board. At the very least if a tool is going to cause so much contention as to question its abundant use, maybe it shouldn't exist at all. If it should exist, then it should offer a wide and broadly-applicable benefit that doesn't make team members think twice about using it even when it perfectly solves the problem they're having. If we're going to be using very in-house tools for our problems, we're not going to derive much benefit if most people choose to keep them dusty in the closet. Some of this is a communication/collaboration thing, which might not always be a strong point of ours. But anything we create, and I don't even care if it's just a class in your language or whether it's a full-blown DSL, the goal should be to get other team members on board as long as other team members are around. We can't help but use each other's stuff, and we should speak up and review if we have problems doing that.

So I'm all about marriage here. I hate Qt with a passion but it's still more productive to marry the MOC and its preprocessor if I'm forced in a team to use it. To try to mitigate its use as much as possible is hardly productive if these are the tools we decided upon. I'm in favor of commitment over some FWB that you just see once every few months. Try to get the maximal benefits if we're going that route, and try not to cheat on him/her too much. You know, serious relationships. That's when we know a design decision is worth its weight is when we can commit to it, and others can commit to it, rather than looking for reasons not to use it. And in the case of in-house things we build (abstractions, interfaces, tools, DSLs, whatever) maybe there's some chance that we screw ourselves committing to something we built rather than a third party, but we can at least control that much better than relying on something outside of our control.

0

In general, when going for a framework with tight coupling or keeping it away as far as possible from your codebase, you basically are in the situation for a make-or-buy decision.

To make this decision, you have to take a few things into account:

  • cost of the framework itself
  • future cost (estimated) of the framework
  • savings by using this framework
  • general risk of making the wrong decision, and cost of moving away from that decision

I find myself unable to continue this answer without looking at camel specifically:

Cost

Camel is open source, therefore it is free for initial use. Check, whether you can get professional support somewhere and for how much, then add a dozen copies of "Camel in Action" into the mix.

Future cost

This is generally the probability that you have to work around breaking changes at any given time. As camel is an apache-project, with more than 50 committers on the list, and with quite a number of heavyweight companies in the contributors list, I find it highly unlikely that you will find yourself at the whim of an unstable upstream developer, who suddenly decides to change the complete API.

Savings

This depends on what you actually do with the framework.

Just use some example routes from your concrete project, and make an estimate in man-days (or even TCO) how much money this had cost you.

// I'd say, probably a day in writing:
from("jms:topic:OrdersTopic").
   filter().method("myBean", "isGoldCustomer").
   to("rest:post:orderprocessingservice");

General risk

... is specific to your business.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.