Fork me on GitHub
#polylith
<
2021-08-02
>
pithyless10:08:09

Just for clarification RE: https://github.com/polyfy/polylith#naming 1. We've internally been using sub-namespaces to group categories of components, but I'm not sure if periods are allowed in poly names (e.g. for components, interfaces, etc)? Would we need to rename a com.company.engine.foo.bar component to com.company.engine-foo-bar? Or is engine.foo.bar allowed for component names? 2. Is there an assumption that everything must belong to :top-ns? Or is that a default, but we can still create components that have a different top-level-ns? Our existing use-case is we've been keeping components in the same monorepo that we have every intention of pulling out into different projects with different top-level-ns at some point.

tengstrand12:08:52

1. Hi! As I said before, I didn’t even know that it was possible to name components like that (it works by a coincidence). I have added a validation The . character is not allowed in brick names to the latest version, so the answer is yes, you should rename these components. I guess you can have both a component called engine, another named engine.foo and a third with the name engine.foo.bar ? Then you could put code in three places and that code could be shared across these components? It feels like that would break encapsulation. If it’s not a problem for you to rename them or if you could convince me that this is a good idea, then I’m open to rethink this decision! 2. Yes, all components and bases live under the tope namespace, and that is something that can’t be changed at the moment. I fiddled around with a version that supported having several top namespaces, but that became very complex, so I abandoned that idea. It also raises questions about how to view them in the info command, if it should be allowed to have bricks with the same name in different top namespaces, and things like that. Maybe we need to prefix the bricks when we view them with the different command, to give them unique names and to show where they belong. There is a great value in having all components at the same place and level, but I understand your need. Maybe the solution is to change these namespaces (manipulate the source code) at the build/release phase. One idea is to change the top namespace/directory at build/release time, so that if the original code lives in e.g. se.mycompany then when you deploy it you just change the top namespace to de.mycompany . I don’t know if that would solve the problem, but it’s an idea at least!

pithyless12:08:35

> As I said before, I didn’t even know that it was possible to name components like that (it works by a coincidence). Sorry, I missed (or forgot) where you wrote about this. I didn't actually try to create a component with . yet, I just assumed it probably would not work well looking at how other parts of poly interact with the component name. RE: 2. I can work around it for now; or push them out into their own libraries. I'm still evaluating how polylith would work in our situation; we also have a monorepo of components built on deps-tools; it would require certain changes to our codebase but I'm considering whether using a tool with more mindshare would outweigh any inconveniences and changes to process.

pithyless12:08:38

Now that I think about it, both #1 and #2 stem from the same mental model in my head:

{"component-x" {:ns-prefix "com.company.component-x"
                :root "components/component-x"
                :alias "c-x"}}
In theory, we could have a unique component name, that is independent of the namespace, where it lives in the project, and by what other names it's known (could even be a set of :aliases). Probably not something you will want to change now, but some food-for-thought for the the future. :)

tengstrand13:08:09

Just so that I understand right. Do you want several components be able to live in the same src directory, e.g. in components/component-x ? Or is it that it should be allowed to let bricks live in different top namespaces, and “only” that (they will still have just one single point of access, the interface )?

pithyless13:08:19

I'm interested in letting bricks live in different top namespaces; they would still share the same interface

pithyless13:08:33

Just a heads up: I'm still wrapping my head around all the implications of having a unified interface with development profiles. Our current monorepo is based more on components via protocols and a unified api namespace (vs classpath changes and polylith interface), which is one of the primary things we would need to modify to migrate. :)

pithyless13:08:00

I guess it doesn't really matter at this point; I'll try porting some of our codebase to get a feel for the poly ergonomics and we'll go from there; adjusting as necessary. Thanks @U1G0HH87L for following up!

tengstrand13:08:17

No problem! To be able to share an interface across several components, they need to live in the same top namespace, otherwise they would not be interchangeable, or we would have to accept that the same component live in several different namespaces, e.g. se.mycompany.invoicing for the interface and com.another.special-invoicing for the implementation. The tool could check that no code lives outside these two, so it would probably be possible to support that.

tengstrand15:08:36

The issue-66 branch is now finally merged into master ! People that have worked in the issue-66 branch, can now switch to master and also use the https://github.com/polyfy/polylith/releases/tag/v0.2.0-alpha10 of the poly tool. For you who have worked in the master branch, now it’s time to migrate your project by using the https://github.com/polyfy/polylith/blob/master/doc/migrate.md command. Feel free to ask questions here, as usual, and good luck with the new version of the tool!

🚀 14
💯 10
seancorfield23:08:37

When writing tests for a new component, do y'all write an interface_test.clj and test purely against the interface.clj or do you write an impl_test.clj and test against the impl.clj or do you write both (in general)?

tengstrand03:08:07

It depends on the scope of the test. Let’s say we have function f1 in impl.clj that I want to test and that I have the same function f1 in the interface, which delegates to f1 in implp.clj , then I prefer to write the test against the interface in interface-test.clj, because it will catch errors in delegation to the implementing namespace. If I want to have a narrower test for a function in impl.clj I will put it in impl-test.clj , I never duplicate the same test for both the interface and the implementation if it’s just a delegation, but if I have e.g. only one or a couple of tests at the interface level, it happens that I can have more tests of a function that is indirectly tested by that interface test, if I want a higher test coverage of that function.

seancorfield04:08:05

Thanks. That makes sense.

👍 3
seancorfield20:08:33

I reorg'd some tests this morning where I had a function in an interface that was no longer needed publicly, so I moved the tests for it into impl_test.clj (after removing the function from the interface). Then I realized some of the other interface_test.clj tests used that function to help verify the behavior of one of the other interface functions (it's a utility function to return a system-specific file path). I agonized a bit over what to do and decided to have the interface_test.clj file require the impl namespace (as well as the interface namespace) so the tests could still access the no-longer-"public" function. Code smell or reasonable approach? (`check` didn't complain about it 🙂 )

furkan3ayraktar20:08:36

Actually, I require implementations from tests quite often. We intentionally let it work that way (so it does not complain during check, only in tests). I believe it makes it easy to use parts of implementation in the tests and prevents mocking as much as possible.

seancorfield20:08:07

Excellent! Thank you @U2BDZ9JG3 for that confirmation.

👍 3
tengstrand03:08:32

Yes, this is an intentional design choice! 🙂

tengstrand04:08:39

In my opinion, code should be open for testing, but protected in production. That brings the best from two worlds.

3
polylith 3
seancorfield20:08:33

I reorg'd some tests this morning where I had a function in an interface that was no longer needed publicly, so I moved the tests for it into impl_test.clj (after removing the function from the interface). Then I realized some of the other interface_test.clj tests used that function to help verify the behavior of one of the other interface functions (it's a utility function to return a system-specific file path). I agonized a bit over what to do and decided to have the interface_test.clj file require the impl namespace (as well as the interface namespace) so the tests could still access the no-longer-"public" function. Code smell or reasonable approach? (`check` didn't complain about it 🙂 )