5 ms·
This discussions tend to focus on the two extremes. What are best practices for making monoliths ready for future SOA design - Workers listening on event bus
by andreasklinger 11y ago
This discussions tend to focus on the two extremes.
What are best practices for making monoliths ready for future SOA design
- Workers listening on event bus
- Database queries abstracted in RepositoryObjects
- ServiceObjects isolating domain logic
- Specs isolated around concepts
- Extracting to plugins (eg vendored gems) if not part of domain logic
What are your recommendations?
- AdrianRossouw 11y agoI've seen a couple of codebases now that have coded themselves into corners and made it nearly impossible to go microservices without a major rewrite. - avoid code sharing wherever possible. It creates an implicit dependency. (If you have a common library or util file, you've done it wrong. try again.) - don't merge your trees: (ie: each component in the code should have it's own readme and tests folder.) - write far more unit tests than functional/integration tests. (if you separate out components later, those tests can't move with them) - if you use an ORM or similar, you are probably going to have a very bad time about it (breaks the no-shared code rule)
- aboodman 11y ago> avoid code sharing wherever possible Err, wut? It sounds like you are saying that pretty much the one reliable guideline in the history of software has become a bad idea. (I have come across places in my career where code sharing was not worthwhile, but they have been rare. And I frequently regretted the decision later.)
- AdrianRossouw 11y agoif you are going to try and separate them out into services later, you need to have the code as compartmentalized as possible. Otherwise when you eventually split them out, you will end up being in a situation where each service needs copies of all the files it required before. This then is a situation where you will have to extract into a library, and make general enough to be used and versioned that way.
- aboodman 11y agoPeople have been building multiple applications from a single codebase for a very long time. Put all the targets on a continuous build, add tests, and you're set. The only sense in which versioning matters at all is that if the protocol the applications talk to each other over has to be versioned, and an application must understand the oldest version of the protocol they could potentially be spoken to over. But things like Thrift and Protocol Buffers have this feature built in. You shouldn't need to version the actual code...
- AdrianRossouw 11y agothe question is about building an application that is easier to split into microservices later. it all comes down to this - http://www.infoq.com/news/2015/01/microservices-sharing-code http://www.infoq.com/news/2015/01/microservices-sharing-code If you have multiple components that are depending on the same code, if you try to split them into multiple services that are being independently deployed, you need to keep the code they are depending on in sync. So making a change to the code shared by multiple services, means you have to deploy multiple services for a single change. I completely agree with you about the protobuf/thrift angle though. If you're in that situation, you are already doing it right.
- thefreeman 11y ago- avoid code sharing wherever possible. It creates an implicit dependency. (If you have a common library or util file, you've done it wrong. try again.) Can you clarify on this a bit? Isn't part of the point of classes and libraries to encapsulate common functionality so that it doesn't need to be separately maintained in multiple places? You listed an ORM as an example, what is a better solution to managing database interaction across an application?
- bliti 11y agoCode sharing is not the same as using the same library in different places. That is managed by a proper dependencies manager and not as issue. The problem is when people take code from the codebase and spread it all over. In one pretty awful scenario, I saw two programmers create a wrapper around the ORM then try and use that all over the place. That made testing awfully difficult because the wrapper was full of errors itself.
- MaulingMonkey 11y ago> Code sharing is not the same as using the same library in different places. Sounds like you're using a different definition than AdrianRossouw. > In one pretty awful scenario, I saw two programmers create a wrapper around the ORM then try and use that all over the place. That made testing awfully difficult because the wrapper was full of errors itself. That sounds like an issue with the wrapper, not so much the code sharing per se. That said, I've seen issues with... "overly shared" code. The example that comes to mind was some UI code on a game - we had various menus, and they all tried to share a huge chunk of programmatic UI layout & control flow logic. However, as so many menus were unique and special snowflakes with their own unique designs and layouts (even justifiably!), this meant the shared code ended up with a lot of special cases. Worse, trying to "fix" the layout to work right in one place usually broke it in another. QA eventually caught almost everything, but it was hell to fix and debug. I would've very gladly eaten a 5x total size increase to the relevant code, full of copy & paste duplication, rife with bugs that were fixed in 7 places but missed in 3 others, just to detangle those menus from each other.
- PretzelFisch 11y agoHow do you deal with business logic getting updated correctly across all modules that write to the database without some shared file or library?
- AdrianRossouw 11y agoonce again, the question is about how to write a system that can be more easily split into microservices later. I would separate business logic into a single service and have all other modules call that using a standard protocol like REST or thrift or something. The issue is that if that logic is being executed all over the system already, it's going to be difficult to break it into a separate service that doesn't do that
- crdoconnor 11y ago>avoid code sharing wherever possible. Oh dear Lord. Are you really serious? >write far more unit tests than functional/integration tests. This is a terrible idea. Integration tests are by their very nature loosely coupled, whereas unit tests are tightly coupled. >(if you separate out components later, those tests can't move with them) If you refactor code under the hood you will inevitably end up throwing away unit tests unless your code is already very loosely coupled. >if you use an ORM or similar, you are probably going to have a very bad time about it Using (good) ORMs helps you to significantly reduce boilerplate code. Reducing boilerplate code is always a good thing.
- deleted 11y ago[deleted]
- lmm 11y agoKeep it simple and YAGNI aggressively - the easiest code to refactor is the code you didn't write yet. Follow ordinary good design practice (single responsibility in particular). Beyond that, don't worry about it yet - one hour's refactoring in the future when you know exactly what you're doing with the services is worth ten now while things are uncertain, so better to save the time.