<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yoel Benítez Fonseca</title>
    <description>The latest articles on DEV Community by Yoel Benítez Fonseca (@ybenitezf).</description>
    <link>https://dev.to/ybenitezf</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F635981%2F18fb467b-d9d5-4131-aea9-60a50cbde23a.jpeg</url>
      <title>DEV Community: Yoel Benítez Fonseca</title>
      <link>https://dev.to/ybenitezf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ybenitezf"/>
    <language>en</language>
    <item>
      <title>Clean architecture: Where to start ?</title>
      <dc:creator>Yoel Benítez Fonseca</dc:creator>
      <pubDate>Tue, 03 Dec 2024 17:03:04 +0000</pubDate>
      <link>https://dev.to/ybenitezf/where-to-start--4i3h</link>
      <guid>https://dev.to/ybenitezf/where-to-start--4i3h</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/ybenitezf/clean-architecture-and-python-polylith-a-real-example-4432"&gt;previous post&lt;/a&gt; we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our problem domain: a ToDo application with some requirements&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ybenitezf/ca-todo-app/pull/1" rel="noopener noreferrer"&gt;A basic repository&lt;/a&gt; configured to use &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; and &lt;a href="https://davidvujic.github.io/python-polylith-docs/" rel="noopener noreferrer"&gt;Python Polylith&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, some decisions are taken care of. We have some of the tools and have decided what the repository will look like.&lt;/p&gt;

&lt;p&gt;This is one of the things that I love about &lt;a href="https://polylith.gitbook.io/polylith" rel="noopener noreferrer"&gt;Polylith&lt;/a&gt;: it doesn't matter what you're coding or how big your organization is, all the repositories will look the same - if you need more than one.&lt;/p&gt;

&lt;p&gt;Your repository structure is consistent, whether you're using FastAPI, Flask, or Django, building single or multiple libraries, or running background tasks with Celery.&lt;/p&gt;

&lt;p&gt;One of the key advantages is the streamlined onboarding process for new developers. Assuming they have a grasp of &lt;a href="https://polylith.gitbook.io/polylith" rel="noopener noreferrer"&gt;Polylith&lt;/a&gt;, they'll quickly become familiar with the project structure: reusable components are in the &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.3.-component" rel="noopener noreferrer"&gt;components&lt;/a&gt; folder, entry points are in the &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.2.-base" rel="noopener noreferrer"&gt;bases&lt;/a&gt; folder, demo scripts are in the &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.4.-development" rel="noopener noreferrer"&gt;development&lt;/a&gt; folder, and so on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entities
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Uncle Bob "The Clean Architecture"&lt;/a&gt; entities are the cornerstone of our architecture, they are the most inner layer of our architecture. So we need to start with them, in Polylith entities should live as components.&lt;/p&gt;

&lt;p&gt;How many components?&lt;/p&gt;

&lt;p&gt;I believe the number of components depends on the size and complexity of your solution. However, I recommend starting with a &lt;strong&gt;single &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.3.-component" rel="noopener noreferrer"&gt;polylith component&lt;/a&gt; for entities&lt;/strong&gt;. This approach helps maintain a clear and focused architecture, especially for smaller projects.&lt;/p&gt;

&lt;p&gt;Why a single component for entities?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This layer encapsulates core business rules that are fundamental to the entire application. By keeping it in a single component, you ensure consistency and avoid duplication.&lt;/li&gt;
&lt;li&gt;A single component simplifies dependency management, as it becomes a dependency for all other layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Avoid third-party dependencies&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;To minimize external dependencies and enhance architectural flexibility, strive to use Python's standard library for representing entities. This includes leveraging data structures like &lt;code&gt;dict&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;enum&lt;/code&gt;, functions, classes and more recently &lt;code&gt;dataclasses&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why avoid third-party libraries like &lt;a href="https://docs.pydantic.dev/latest/concepts/models/" rel="noopener noreferrer"&gt;Pydantic&lt;/a&gt; or &lt;a href="https://docs.djangoproject.com/en/5.1/topics/db/models/" rel="noopener noreferrer"&gt;Django Models&lt;/a&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coupling to external frameworks&lt;/strong&gt;: Relying on these libraries can introduce unnecessary coupling to specific frameworks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increased complexity&lt;/strong&gt;: External libraries can add complexity and potential maintenance issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced flexibility&lt;/strong&gt;: By limiting external dependencies, you can more easily adapt to changes in requirements or technology.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By adhering to these principles, you can create a robust and maintainable architecture that is resilient to future changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  ToDo entities
&lt;/h2&gt;

&lt;p&gt;Our example is straightforward, with the core entity being the "todo item" for Gordon. We can add a new component to our repository, but choosing the right name is crucial.&lt;/p&gt;

&lt;p&gt;While it might be tempting to use generic names like "core" or "main," it's essential to select names that are meaningful within the domain context. Ideally, these names should align with the terminology used by the client or product owner. By using domain-specific names, we enhance code readability and maintainability, making it easier for both developers and stakeholders to understand the project's structure.&lt;/p&gt;

&lt;p&gt;The repository workspace name is defined as &lt;code&gt;todo&lt;/code&gt;. Consequently, all our imports will follow the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;todo.XYZ&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;todo.XYZ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For simplicity in this example, we'll use &lt;code&gt;entities&lt;/code&gt; as the component name. However, in real-world scenarios, consider naming conventions that reflect your domain. For instance, if your application revolves around document recovery, a component named &lt;code&gt;recovery&lt;/code&gt; would be appropriate. Similarly, a gaming application might use &lt;code&gt;tournaments_entities&lt;/code&gt; for clarity.&lt;/p&gt;

&lt;p&gt;Creating the component with Python Polylith is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry poly create component &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;entities
poetry poly &lt;span class="nb"&gt;sync
&lt;/span&gt;poetry &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="c"&gt;# it may be necessary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add a python package in the components folder, this are the new entries in the source tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./components
└── todo
    └── entities
        ├── __init__.py
        └── core.py
./test/components
└── todo
    └── entities
        ├── __init__.py
        └── test_core.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The python-polylith tool will generate test examples for us, which is a nice feature. This behavior can be changed in the &lt;code&gt;workspace.toml&lt;/code&gt; file by setting the &lt;code&gt;enabled = true&lt;/code&gt; value to &lt;code&gt;false&lt;/code&gt; in the &lt;code&gt;[tool.polylith.test]&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;In the new &lt;code&gt;entities&lt;/code&gt; component, two files are added: &lt;code&gt;__init__.py&lt;/code&gt; and &lt;code&gt;core.py&lt;/code&gt;. You can rename the &lt;code&gt;core.py&lt;/code&gt; module to better suit your needs. The common practice is to expose the public API of the package through &lt;code&gt;__init__.py&lt;/code&gt;, while maintaining internal organization within other modules like &lt;code&gt;core.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the requirements, we has, at the moment, only one entity, the ToDo item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoItem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;is_done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="n"&gt;due_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing such a simple entity might seem unnecessary, but I prefer to test at least the presence of all fields. While this may not seem crucial in smaller projects with fewer contributors, it can prevent significant issues in larger projects with many developers. Removing a single field from the entity can inadvertently break various parts of the application.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/ybenitezf/ca-todo-app/pull/2/files" rel="noopener noreferrer"&gt;the pull request for this part&lt;/a&gt;, you will see that i have added some basic tests for this entity. &lt;/p&gt;

&lt;p&gt;With some tests already defined, I took the opportunity to add a GitHub workflow to automatically run the tests for each pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ybenitezf/ca-todo-app/pull/2" rel="noopener noreferrer"&gt;Application basic entities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ybenitezf/ca-todo-app/actions/runs/12144420984/job/33863712292" rel="noopener noreferrer"&gt;CI setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is next: Let's talk about persistence &lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>architecture</category>
      <category>polylith</category>
    </item>
    <item>
      <title>Clean architecture and Python Polylith - a real example</title>
      <dc:creator>Yoel Benítez Fonseca</dc:creator>
      <pubDate>Sat, 30 Nov 2024 17:16:00 +0000</pubDate>
      <link>https://dev.to/ybenitezf/clean-architecture-and-python-polylith-a-real-example-4432</link>
      <guid>https://dev.to/ybenitezf/clean-architecture-and-python-polylith-a-real-example-4432</guid>
      <description>&lt;p&gt;This is the first in a &lt;a href="https://dev.to/ybenitezf/series/29627"&gt;series of posts&lt;/a&gt; where I will hopefully try to combine the concepts of &lt;a href="https://blog.cleancoder.com/uncle-bob/2011/11/22/Clean-Architecture.html" rel="noopener noreferrer"&gt;Clean Architecture&lt;/a&gt; and &lt;a href="https://polylith.gitbook.io/" rel="noopener noreferrer"&gt;Polylith&lt;/a&gt; by building a real-world example with Python.&lt;/p&gt;

&lt;p&gt;I believe that both philosophies are not incompatible. While &lt;em&gt;the clean architecture principles&lt;/em&gt; provide a way to achieve separation of concerns, Polylith allows us to manage the code repository and dependencies efficiently.&lt;/p&gt;

&lt;p&gt;I'll demonstrate how to combine those two by building one or more applications using &lt;a href="https://davidvujic.github.io/python-polylith-docs/" rel="noopener noreferrer"&gt;Python polylith&lt;/a&gt; in the repository &lt;a href="https://github.com/ybenitezf/ca-todo-app" rel="noopener noreferrer"&gt;https://github.com/ybenitezf/ca-todo-app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the initial setup, I used the Cookiecutter template from my &lt;a href="https://dev.to/ybenitezf/cookiecutter-for-fast-starting-with-polylith-4fp6"&gt;previous article&lt;/a&gt; to initialize the solution repository. I will be creating merge requests to add features to the solution, for the moment this is the firsts pull request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ybenitezf/ca-todo-app/pull/1" rel="noopener noreferrer"&gt;https://github.com/ybenitezf/ca-todo-app/pull/1&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The example application domain
&lt;/h2&gt;

&lt;p&gt;Let's use the ToDo example, we will borrow the product requirements from &lt;a href="https://medium.com/@EddieMachete/designing-a-typescript-todo-list-application-following-clean-architecture-principles-8bd7b77bae3d" rel="noopener noreferrer"&gt;this article&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Gordon is responsible of the development of RHI’s clinical reports. He is constantly dealing with customer update requests required to improve the efficacy of the reports. Lately he has been dealing with a high volume of requests. He has been having trouble tracking his progress.&lt;/p&gt;

&lt;p&gt;His main objective is to complete all of the requests as fast as possible. His main goal is to feel a degree of accomplished at the end of every work day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To help Gordon with his work, we will write a ToDo list application for Gordon to keep track of his tasks and progress. By marking things as done, we hope he can feel accomplished at the end of the day. Our application will also provide a storage mechanism so that we can save Gordon's progress.&lt;/p&gt;

&lt;p&gt;The use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View the todo list, applying some filter's optionally&lt;/li&gt;
&lt;li&gt;Add new todo item&lt;/li&gt;
&lt;li&gt;Complete item&lt;/li&gt;
&lt;li&gt;Edit item&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;At this moment, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The problem/application domain: a todo application&lt;/li&gt;
&lt;li&gt;The basic set of tools that we will be using: Python and python-polylith&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In future articles, we will add the solution and expand the domain a little to explain and demonstrate some concepts.&lt;/p&gt;

&lt;p&gt;See ya.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>polylith</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Cookiecutter for fast starting with polylith</title>
      <dc:creator>Yoel Benítez Fonseca</dc:creator>
      <pubDate>Fri, 29 Nov 2024 20:37:05 +0000</pubDate>
      <link>https://dev.to/ybenitezf/cookiecutter-for-fast-starting-with-polylith-4fp6</link>
      <guid>https://dev.to/ybenitezf/cookiecutter-for-fast-starting-with-polylith-4fp6</guid>
      <description>&lt;p&gt;Presenting to you a Python cookiecutter for fast starting with polylith in Python. If you do not know what polylith is &lt;a href="https://polylith.gitbook.io/polylith" rel="noopener noreferrer"&gt;read the documentation &lt;/a&gt;, for the impatient reader:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Polylith is a software architecture that aims to build simple, maintainable, testable, and scalable backend systems. It does this by applying functional thinking at the system scale, treating code as building blocks that can be combined into features.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And &lt;a href="https://davidvujic.github.io/python-polylith-docs/" rel="noopener noreferrer"&gt;python-polylith&lt;/a&gt; is the tool that allow us to implement this in Python.&lt;/p&gt;

&lt;p&gt;I won't go into details about the advantages of this approach. In this article I introduce you to &lt;a href="https://github.com/ybenitezf/poetry-poly-cc" rel="noopener noreferrer"&gt;poetry-poly-cc&lt;/a&gt;, a highly opinionated cookiecutter for starting a project with python-polylith.&lt;/p&gt;

&lt;p&gt;You can start by installing &lt;a href="https://cookiecutter.readthedocs.io/en/stable/README.html#installation" rel="noopener noreferrer"&gt;cookiecutter&lt;/a&gt; and generating a project with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cookiecutter https://github.com/ybenitezf/poetry-poly-cc.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer the questions and you are good. You should endup with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── LICENSE
├── README.md
├── bases
├── build-packages.sh
├── components
├── development
│   └── __init__.py
├── poetry.toml
├── projects
├── pyproject.toml
├── update-locks.sh
└── workspace.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The firsts steps are included in the README.md:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install poetry: &lt;a href="https://python-poetry.org/docs/#installation" rel="noopener noreferrer"&gt;https://python-poetry.org/docs/#installation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add polylith tooling: &lt;a href="https://davidvujic.github.io/python-polylith-docs/installation/" rel="noopener noreferrer"&gt;https://davidvujic.github.io/python-polylith-docs/installation/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
poetry &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="c"&gt;# install pre-commit hook&lt;/span&gt;
poetry run pre-commit &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="c"&gt;# install pre-commit dependencies&lt;/span&gt;
poetry run pre-commit run &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What is included
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Poetry is configured to create the virtualenv in the project folder (see &lt;code&gt;poetry.toml&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.pytest.org/en/stable/" rel="noopener noreferrer"&gt;pytest&lt;/a&gt; is added as a test dependency, also includes some goodies for pytest: &lt;code&gt;pytest-mock&lt;/code&gt;, &lt;code&gt;pytest-cov&lt;/code&gt; and &lt;code&gt;pytest-asyncio&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pre-commit&lt;/code&gt; &amp;amp; &lt;code&gt;ruff&lt;/code&gt; as dev dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mypy&lt;/code&gt; for static typing check, integrated with &lt;code&gt;pre-commit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The support scripts &lt;code&gt;build-packages.sh&lt;/code&gt; and &lt;code&gt;update-locks.sh&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Recommended vscode extensions&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>python</category>
      <category>polylith</category>
      <category>monorepo</category>
      <category>programming</category>
    </item>
    <item>
      <title>Aws CDK App with polylith code architecture</title>
      <dc:creator>Yoel Benítez Fonseca</dc:creator>
      <pubDate>Tue, 09 May 2023 19:18:26 +0000</pubDate>
      <link>https://dev.to/ybenitezf/aws-cdk-app-with-polylith-code-architecture-30e3</link>
      <guid>https://dev.to/ybenitezf/aws-cdk-app-with-polylith-code-architecture-30e3</guid>
      <description>&lt;h2&gt;
  
  
  Monorepo architecture for Python code with Polylith and Poetry
&lt;/h2&gt;

&lt;p&gt;By: Yoel Benitez Fonseca&lt;/p&gt;

&lt;p&gt;Review and Corrections by: Robmay S. Garcia&lt;/p&gt;

&lt;p&gt;This article explores a technique or methodology for achieving a "monorepo" architecture for code by leveraging the &lt;a href="https://polylith.gitbook.io/polylith/" rel="noopener noreferrer"&gt;Polylith&lt;/a&gt; philosophy, along with a few &lt;a href="https://python-poetry.org/docs/" rel="noopener noreferrer"&gt;poetry&lt;/a&gt; plugins, for implementation in Python CDK applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;Let's go ahead and get our dependencies installed for poetry and the plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://install.python-poetry.org | python3 -
poetry self add poetry-multiproject-plugin
poetry self add poetry-polylith-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will also need  &lt;code&gt;AWS CDK&lt;/code&gt; installed on your system. I will recommend you to follow the &lt;a href="https://cdkworkshop.com/15-prerequisites.html" rel="noopener noreferrer"&gt;requirements section of the aws cdk workshop site&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; aws-cdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here I leave some additional readings about poetry and its plugins.&lt;a href="https://github.com/DavidVujic/poetry-multiproject-plugin" rel="noopener noreferrer"&gt;multiproject&lt;/a&gt; and for &lt;a href="https://davidvujic.github.io/python-polylith-docs/" rel="noopener noreferrer"&gt;polylith&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting point
&lt;/h2&gt;

&lt;p&gt;Let's get started. As a starting point we will be using the final version of the CDK Python Workshop. Simply clone the code from the repository  &lt;a href="https://github.com/aws-samples/aws-cdk-intro-workshop/tree/master/code/python/main-workshop" rel="noopener noreferrer"&gt;https://github.com/aws-samples/aws-cdk-intro-workshop/tree/master/code/python/main-workshop&lt;/a&gt;. Our &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/dc0033ffb7bfc30f604692948a9390b228c92af6" rel="noopener noreferrer"&gt;first commit&lt;/a&gt; will be like this and the resulting source tree should looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── app.py
├── cdk.json
├── cdk_workshop
│   ├── cdk_workshop_stack.py
│   ├── hitcounter.py
│   └── __init__.py
├── lambda
│   ├── hello.py
│   └── hitcount.py
├── README.md
├── requirements-dev.txt
├── requirements.txt
└── source.bat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's turn this source tree into a poetry project by executing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When asked for the main and development dependencies answer no, we will add then later. The result should look like (&lt;code&gt;pyproject.toml&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.poetry]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk-polylith"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Yoel Benitez Fonseca &amp;lt;ybenitezf@gmail.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;readme&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"README.md"&lt;/span&gt;
&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;[{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_polylith"&lt;/span&gt;&lt;span class="err"&gt;}]&lt;/span&gt;

&lt;span class="nn"&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.10"&lt;/span&gt;

&lt;span class="nn"&gt;[build-system]&lt;/span&gt;
&lt;span class="py"&gt;requires&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"poetry-core"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;build-backend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"poetry.core.masonry.api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, let's add a poetry configuration file &lt;code&gt;poetry.toml&lt;/code&gt; to have poetry build the python virtual environment in the project folder before installing the dependencies. The file content should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[virtualenvs]&lt;/span&gt;
&lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;".venv"&lt;/span&gt;
&lt;span class="py"&gt;in-project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/08b4391ea1298c86a92ec3c7829dde22bba00113" rel="noopener noreferrer"&gt;a commit&lt;/a&gt; with what we already have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring polylith
&lt;/h2&gt;

&lt;p&gt;Before delving into the code, I strongly recommend you to read the following polylith core concepts: &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.1.-workspace" rel="noopener noreferrer"&gt;workspace&lt;/a&gt;, &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.3.-component" rel="noopener noreferrer"&gt;component&lt;/a&gt;, &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.2.-base" rel="noopener noreferrer"&gt;base&lt;/a&gt;, &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.6.-project" rel="noopener noreferrer"&gt;project&lt;/a&gt; and &lt;a href="https://polylith.gitbook.io/polylith/architecture/2.4.-development" rel="noopener noreferrer"&gt;development project&lt;/a&gt; taking into account that the &lt;a href="https://github.com/DavidVujic/python-polylith" rel="noopener noreferrer"&gt;python-polylith&lt;/a&gt; is an adaptation of those concepts for Python.&lt;/p&gt;

&lt;p&gt;For those of you who are impatient, running the following command (only once) in our repository will create the necessary folder structure for our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry poly create workspace &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cdk_workshop"&lt;/span&gt; &lt;span class="nt"&gt;--theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;loose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: The &lt;code&gt;--name&lt;/code&gt; parameter here will set the base package structure, all the code then will be imported from this namespace, for example &lt;code&gt;from cdk_workshop ...&lt;/code&gt; for more details on this read the &lt;a href="https://davidvujic.github.io/python-polylith-docs/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After running the above command our source tree will look like this, note the new folders created (bases, components, development, and projects):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── app.py
├── bases
├── cdk.json
├── cdk_workshop
│   ├── cdk_workshop_stack.py
│   ├── hitcounter.py
│   └── __init__.py
├── components
├── development
├── lambda
│   ├── hello.py
│   └── hitcount.py
├── poetry.toml
├── projects
├── pyproject.toml
├── README.md
├── requirements-dev.txt
├── requirements.txt
├── source.bat
└── workspace.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;workspace.toml&lt;/code&gt; file will configure the behavior of the &lt;code&gt;poetry poly ...&lt;/code&gt; commands&lt;/p&gt;

&lt;p&gt;Let's create a new &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/bfc66d18ba91139e46251e446f2fbb3d14253f67" rel="noopener noreferrer"&gt; commit&lt;/a&gt;. From now on, we will be moving the old code to this new structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing project requirements.
&lt;/h2&gt;

&lt;p&gt;Before we go any further let's install the poetry project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: ignore the warning about the project not containing any element's&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And now we move our dependencies from &lt;code&gt;requirements.txt&lt;/code&gt; and &lt;code&gt;requirements-dev.txt&lt;/code&gt; to the &lt;code&gt;pyproject.toml&lt;/code&gt; format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add aws-cdk-lib~&lt;span class="o"&gt;=&lt;/span&gt;2.68
poetry add &lt;span class="s1"&gt;'constructs&amp;gt;=10.0.0,&amp;lt;11.0.0'&lt;/span&gt;
poetry add cdk-dynamo-table-view&lt;span class="o"&gt;==&lt;/span&gt;0.2.438
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for dev requirements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add &lt;span class="nv"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;7.2.2 &lt;span class="nt"&gt;-G&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can remove  &lt;code&gt;requirements.txt&lt;/code&gt; and &lt;code&gt;requirements-dev.txt&lt;/code&gt; files because they will be managed by the &lt;code&gt;pyproject.toml&lt;/code&gt;. The content of the file will now look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fows5ycgnhoek2ell67sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fows5ycgnhoek2ell67sc.png" alt="pyproject.toml after adding the requirements" width="717" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/a05638728e299fadd5f7498e00abcb648956d590" rel="noopener noreferrer"&gt;changes will be visible in this commit&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note&lt;/strong&gt;: Poetry developers recommend to add the &lt;code&gt;poetry.lock&lt;/code&gt; to the repository. Other developers have reported problems with architecture changes and the &lt;code&gt;.lock&lt;/code&gt; file, so I will leave it up to you to decide if you want to use it or not.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Components
&lt;/h1&gt;

&lt;p&gt;From the polylith documentation (&lt;a href="https://polylith.gitbook.io/polylith/architecture/2.3.-component):" rel="noopener noreferrer"&gt;https://polylith.gitbook.io/polylith/architecture/2.3.-component):&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A component is an encapsulated block of code that can be assembled together with a base (it's often just a single base) and a set of components and libraries into services, libraries or tools. Components achieve encapsulation and composability by separating their private implementation from their public interface.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in CDK term's our component should be &lt;em&gt;Stacks&lt;/em&gt; or &lt;em&gt;Constructs&lt;/em&gt; since this are the reusable parts.&lt;/p&gt;

&lt;p&gt;In this application we have the &lt;code&gt;HitCounter&lt;/code&gt; construct and the &lt;code&gt;CdkWorkshopStack&lt;/code&gt; stack, lets add them as components to our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry poly create component --name hit_counter
poetry poly create component --name cdk_workshop_stack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will get a new directory under &lt;code&gt;components&lt;/code&gt; with the name of the workspace (&lt;code&gt;cdk_workshop&lt;/code&gt;) and under this a python package for each of the components. The same has happened to the tests folder (that is why we used &lt;code&gt;--theme=loose&lt;/code&gt; when creating the workspace).&lt;/p&gt;

&lt;p&gt;Next, we need to modify &lt;code&gt;pyproject.toml&lt;/code&gt; to recognize this components. Edit and add the following to the package property in the &lt;code&gt;[tool.poetry]&lt;/code&gt; section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hit_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/cdk_workshop_stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make sure all is fine, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry run pytest &lt;span class="nb"&gt;test&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if we run  &lt;code&gt;poetry poly info&lt;/code&gt; we will see our new components listed under the bricks section&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ff7di6dixc18qoklswk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ff7di6dixc18qoklswk.png" alt="poetry poly info" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, let's &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/b77d8d5272bd629efb3588d6df151e19079c8061" rel="noopener noreferrer"&gt;commit this changes&lt;/a&gt; before moving into the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;hit_counter&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;Now that we have a &lt;code&gt;HitCounter&lt;/code&gt; construct, we will copy the code in &lt;code&gt;cdk_workshop/hitcounter.py&lt;/code&gt; to &lt;code&gt;components/cdk_workshop/hit_counter/core.py&lt;/code&gt; by executing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;cdk_workshop/hitcounter.py components/cdk_workshop/hit_counter/core.py
git &lt;span class="nb"&gt;rm &lt;/span&gt;cdk_workshop/hitcounter.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code in this construct will need additional refactoring but we will come back to it later, for now we &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/9e17a1f7ff9e2537453ee7e80bacfd665d10a647" rel="noopener noreferrer"&gt;commit this change as is&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;cdk_workshop_stack&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;We repeat the same process for the  &lt;code&gt;CdkWorkshopStack&lt;/code&gt; component, just change the file name and destination as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp cdk_workshop/cdk_workshop_stack.py components/cdk_workshop/cdk_workshop_stack/core.py
git rm cdk_workshop/*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, pay attention to this little but important detail. There is a dependency between both components, &lt;code&gt;cdk_workshop_stack&lt;/code&gt; needs the construct defined in &lt;code&gt;hit_counter&lt;/code&gt; so we need to edit &lt;code&gt;components/cdk_workshop/cdk_workshop_stack/core.py&lt;/code&gt; file to fix the import statement as shown in line 8 of the following snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;constructs&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Construct&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_lambda&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;aws_apigateway&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;apigw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cdk_dynamo_table_view&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TableViewer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cdk_workshop.hit_counter.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HitCounter&lt;/span&gt;

&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Now we are able to use the fully qualified path to the class component like (&lt;code&gt;cdk_workshop.hit_counter.core&lt;/code&gt;). The path is composed by &lt;code&gt;cdk_workshop&lt;/code&gt; the workspace, &lt;code&gt;hit_counter&lt;/code&gt; the component, and &lt;code&gt;core&lt;/code&gt; the module in &lt;code&gt;hit_counter&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's add &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/c57b58c0a0f15044f59dbb52c6d981ba83d02165" rel="noopener noreferrer"&gt;another commit&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bases
&lt;/h2&gt;

&lt;p&gt;From the polylith documentation (&lt;a href="https://polylith.gitbook.io/polylith/architecture/2.2.-base" rel="noopener noreferrer"&gt;https://polylith.gitbook.io/polylith/architecture/2.2.-base&lt;/a&gt;), &lt;em&gt;bases&lt;/em&gt; are the building blocks that exposes a public API to the outside world.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A base has a "thin" implementation which delegates to components where the business logic is implemented.&lt;br&gt;
A base has one role and that is to be a bridge between the outside world and the logic that performs the "real work", our components. Bases don't perform any business logic themselves, they only delegate to components.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, in the context of the AWS CDK application the candidate for a base will be the module that defines the application and do the synthesis, in other words the code that now resides on &lt;code&gt;app.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's add a base to the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry poly create base &lt;span class="nt"&gt;--name&lt;/span&gt; workshop_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like in the case of the components, the previous command, will add a new package but in the bases directory. This time, under the path &lt;code&gt;bases/cdk_workshop/workshop_app&lt;/code&gt; with a module for us to define the code of our base - &lt;code&gt;poetry poly&lt;/code&gt; will add a demo test code too.&lt;/p&gt;

&lt;p&gt;We need to alter our package list on &lt;code&gt;pyproject.toml&lt;/code&gt; to add the newly created base to the Python project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/workshop_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hit_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/cdk_workshop_stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's copy the code and fix the imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;app.py bases/cdk_workshop/workshop_app/core.py
git &lt;span class="nb"&gt;rm &lt;/span&gt;app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The file content should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aws_cdk&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cdk_workshop.cdk_workshop_stack.core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CdkWorkshopStack&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;CdkWorkshopStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cdk-workshop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result can be seen &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/db9974030b63d42d519fd5ea1de9969ccc40e087" rel="noopener noreferrer"&gt;in this commit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;poetry poly info&lt;/code&gt; you should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F143ofyw8wag2y2dta7hk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F143ofyw8wag2y2dta7hk.png" alt="Workspace Summary" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Remarks
&lt;/h3&gt;

&lt;p&gt;I suggest the use of a single base for each cdk application, but if more than one is necessary, each base should reuse the stacks and constructs defined in the components.&lt;/p&gt;

&lt;p&gt;If you are facing a large CDK project, I recommend maintaining a single component package (a single component in polylith is a python package) for all the constructs, one construct per module. And a component for each Stack, the reason being to maintain a single source of dependencies between the components in the project: &lt;code&gt;construct component -&amp;gt;  stack component&lt;/code&gt; assuming the stack's components do not depend on the others stack components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Projects configure Polylith's deployable artifacts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, projects define what we deploy, we combine one (or several bases but that's rare) base and several components into an artifact that allow us to deploy our code.&lt;/p&gt;

&lt;p&gt;In polylith the projects live in the &lt;code&gt;projects&lt;/code&gt; folder and they &lt;strong&gt;&lt;em&gt;should not contain code&lt;/em&gt;&lt;/strong&gt; unless such code is related to the deployment or building of the artifacts, in other words &lt;strong&gt;&lt;em&gt;no python code there&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A CDK application is defined by the &lt;code&gt;cdk.json&lt;/code&gt; file, in our case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python3 app.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@aws-cdk/core:stackRelativeExports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@aws-cdk/aws-rds:lowercaseDbIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@aws-cdk/aws-lambda:recognizeVersionProps"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the content of the &lt;code&gt;"app"&lt;/code&gt; key, we've removed &lt;code&gt;app.py&lt;/code&gt; and now we need to do something else, beginning by adding a new project to our polylith repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry poly create project &lt;span class="nt"&gt;--name&lt;/span&gt; cdk_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project name can be anything you need or want, this will be used to build a python package. Now the projects folder have a new subfolder &lt;code&gt;cdk_app&lt;/code&gt; with a &lt;code&gt;pyproject.toml&lt;/code&gt; file on it. In this file is where we combine our bases and components to build the artifact to deploy. Edit this file to add our include statements under the &lt;code&gt;package&lt;/code&gt; property as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/workshop_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hit_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/cdk_workshop_stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we've added a &lt;code&gt;../../&lt;/code&gt; to bases and components because this pyproject file is two levels down in the path&lt;/p&gt;

&lt;p&gt;Next, we need to add the necessary dependencies form the &lt;code&gt;pyproject.toml&lt;/code&gt; in the root folder, from there we only copy what we need for the bases and components, no dev dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.10"&lt;/span&gt;
&lt;span class="py"&gt;aws-cdk-lib&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;constructs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mf"&gt;11.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;cdk-dynamo-table-view&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.438"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final result should be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.poetry]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_app"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Yoel Benitez Fonseca &amp;lt;ybenitezf@gmail.com&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;license&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;

&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/workshop_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hit_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/cdk_workshop_stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.10"&lt;/span&gt;
&lt;span class="py"&gt;aws-cdk-lib&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;constructs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mf"&gt;11.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;cdk-dynamo-table-view&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.2.438"&lt;/span&gt;

&lt;span class="nn"&gt;[tool.poetry.group.dev.dependencies]&lt;/span&gt;

&lt;span class="nn"&gt;[build-system]&lt;/span&gt;
&lt;span class="py"&gt;requires&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;["poetry-core&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="py"&gt;build-backend&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"poetry.core.masonry.api"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;poetry poly info&lt;/code&gt; will show:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qycwdgpi3fqult0mjwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qycwdgpi3fqult0mjwp.png" alt="Workspace Summary" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see a new column has appeared and the bricks (bases and components) used by the project are marked.&lt;/p&gt;

&lt;p&gt;Next, move the &lt;code&gt;cdk.json&lt;/code&gt; file to the project folder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;cdk.json projects/cdk_app/cdk.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But because we move our app object to the &lt;code&gt;bases/cdk_workshop/workshop_app/core.py&lt;/code&gt; module we need to edit &lt;code&gt;cdk.json&lt;/code&gt; and change the &lt;code&gt;app&lt;/code&gt; entry to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "app": "python3 -m cdk_workshop.workshop_app.core"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add a &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/8a581b042588a0ec0271047fa293d143df0235fc" rel="noopener noreferrer"&gt;checkpoint here and commit our changes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  cdk project new home
&lt;/h2&gt;

&lt;p&gt;At this point we should be able to deploy our CDK application (theoretically speaking), let's test that assumption:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;projects/cdk_app
poetry build-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;build-project&lt;/code&gt; command will create a &lt;code&gt;dist&lt;/code&gt; directory under &lt;code&gt;projects/cdk_app&lt;/code&gt; containing the python package.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This new directory need to be include in the &lt;code&gt;.gitignore&lt;/code&gt; file. To make this step simpler, copy the content of the &lt;a href="https://github.com/github/gitignore/blob/main/Python.gitignore" rel="noopener noreferrer"&gt;recommended gitignore for python&lt;/a&gt; file and add it to the .gitignore in the repository root as shown in &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/0c0eda0cf6f2d75e6899a8e18b2374663d4a8b8d" rel="noopener noreferrer"&gt;this example commit&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1tz7t111dvxwnzv2li9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1tz7t111dvxwnzv2li9.png" alt="Here is a view of the project folder file tree" width="744" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This python package contains our CDK app. So, to test our theory we need to created a python virtual env, install this package, and run &lt;code&gt;cdk synth&lt;/code&gt; (under the &lt;code&gt;projects/cdk_app&lt;/code&gt; folder) to see the CloudFormation template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;dist/cdk_app-0.1.0-py3-none-any.whl
cdk synth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But wait, we get and error. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RuntimeError: Cannot find asset at cdk_polylith/projects/cdk_app/lambda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The root cause for this error is that the previous implementation assumed that any cdk command would be execute on the root of the repository but our app has been moved to &lt;code&gt;projects/cdk_app&lt;/code&gt;. To fix this, we need to move the &lt;code&gt;lambda&lt;/code&gt; folder under &lt;code&gt;projects/cdk_app&lt;/code&gt; and run &lt;code&gt;cdk synth&lt;/code&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../../
&lt;span class="nb"&gt;mv &lt;/span&gt;lambda/ projects/cdk_app/
&lt;span class="nb"&gt;cd &lt;/span&gt;projects/cdk_app/
cdk synth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now all should work great!!! ... ummm no, not really. The idea behind polylith is that all code should live in the components or bases folders.&lt;/p&gt;

&lt;p&gt;So, let's go back, discard these last changes and solve this problem in the polylith way - (don't forget to exit the venv created for the &lt;code&gt;cdk_app&lt;/code&gt; project).&lt;/p&gt;

&lt;h2&gt;
  
  
  Include lambda functions code, the polilyth way.
&lt;/h2&gt;

&lt;p&gt;In this project we have 2 lambdas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./lambda/
├── hello.py
└── hitcount.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plan here is to add to bases (one for each function) to the project. Both are pretty simple, only &lt;code&gt;hitcount.py&lt;/code&gt; have an external dependency to boto3.&lt;/p&gt;

&lt;p&gt;Let's add the bases first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry poly create base --name hello_lambda
poetry poly create base --name hitcounter_lambda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If these functions shared code (e.g: something that could be refactored so that they both use it), it would be a good idea to add a new component for this feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, we add this new bases to the main &lt;code&gt;pyproject.toml&lt;/code&gt; packages property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/workshop_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hello_lambda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hitcounter_lambda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hit_counter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/cdk_workshop_stack"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"components"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding any dependencies too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;poetry add boto3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;poetry install &amp;amp;&amp;amp; poetry run pytest test/&lt;/code&gt; to ensure all is correct.&lt;/p&gt;

&lt;p&gt;Now, let's move the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;lambda/hello.py bases/cdk_workshop/hello_lambda/core.py
&lt;span class="nb"&gt;mv &lt;/span&gt;lambda/hitcount.py bases/cdk_workshop/hitcounter_lambda/core.py
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; lambda/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add a &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/61d24f3917fb90a822bfca542bfa1576c01dc3a7" rel="noopener noreferrer"&gt;checkpoint here and commit our changes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The trick now is to generate a python package for each lambda function and use the bundling options of the lambda cdk construct to inject our code and requirements for the lambdas. Let's begin by adding the projects for each lambda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry poly create project &lt;span class="nt"&gt;--name&lt;/span&gt; hello_lambda_project
poetry poly create project &lt;span class="nt"&gt;--name&lt;/span&gt; hitcounter_lambda_project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the &lt;code&gt;cdk_app&lt;/code&gt;, the &lt;code&gt;projects/hello_lambda_project/pyproject.toml&lt;/code&gt; should reference the corresponding &lt;code&gt;hello_lambda&lt;/code&gt; base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;

&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hello_lambda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="err"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, the same for &lt;code&gt;projects/hitcounter_lambda_project/pyproject.toml&lt;/code&gt; for &lt;code&gt;hitcounter_lambda&lt;/code&gt; - including the dependency for &lt;code&gt;boto3&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;packages&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="py"&gt;{include&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"cdk_workshop/hitcounter_lambda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"../../bases"&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nn"&gt;[tool.poetry.dependencies]&lt;/span&gt;
&lt;span class="py"&gt;python&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^3.10"&lt;/span&gt;
&lt;span class="py"&gt;boto3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"^1.26.123"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;CdkWorkshopStack&lt;/code&gt; file code we change the lambda function definition to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

        &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HelloHandler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON_3_9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;bundling&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;BundlingOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON_3_9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bundling_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pip install -r requirements.txt -t&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; /asset-output &amp;amp;&amp;amp; cp -au . /asset-output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cdk_workshop.hello_lambda.core.handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;handler&lt;/code&gt; declaration, like in &lt;code&gt;cdk.json&lt;/code&gt; file we are using the package fully qualified namespace to declare our handler. The &lt;code&gt;_lambda.Runtime.PYTHON_3_9.bundling_image&lt;/code&gt; property will build the lambda distribution using a &lt;code&gt;requirements.txt&lt;/code&gt; file that we will generate.&lt;/p&gt;

&lt;p&gt;Let's repeat the process for the &lt;code&gt;hitcounter_lambda&lt;/code&gt;. In &lt;code&gt;components/cdk_workshop/hit_counter/core.py&lt;/code&gt; we change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
            &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cdk_workshop.hitcounter_lambda.core.handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda/hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;bundling&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;BundlingOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON_3_9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bundling_image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pip install -r requirements.txt -t&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; /asset-output &amp;amp;&amp;amp; cp -au . /asset-output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PYTHON_3_9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the required folders (assets folders) to the &lt;code&gt;cdk_app&lt;/code&gt; project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p mkdir -p projects/cdk_app/lambda/{hello,hitcounter}
touch projects/cdk_app/lambda/{hello,hitcounter}/requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, time for a &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/61d24f3917fb90a822bfca542bfa1576c01dc3a7" rel="noopener noreferrer"&gt;checkpoint and commit our changes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ok, let's try the deploy again. First, we build the lambda packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;projects/hello_lambda_project
poetry build-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ../hitcounter_lambda_project/
poetry build-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ../../
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our projects folder structure should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./projects/
├── cdk_app
│   ├── cdk.json
│   ├── dist
│   │   ├── cdk_app-0.1.0-py3-none-any.whl
│   │   └── cdk_app-0.1.0.tar.gz
│   ├── lambda
│   │   ├── hello
│   │   │   └── requirements.txt
│   │   └── hitcounter
│   │       └── requirements.txt
│   └── pyproject.toml
├── hello_lambda_project
│   ├── dist
│   │   ├── hello_lambda_project-0.1.0-py3-none-any.whl
│   │   └── hello_lambda_project-0.1.0.tar.gz
│   └── pyproject.toml
└── hitcounter_lambda_project
    ├── dist
    │   ├── hitcounter_lambda_project-0.1.0-py3-none-any.whl
    │   └── hitcounter_lambda_project-0.1.0.tar.gz
    └── pyproject.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will need to add the &lt;code&gt;.whl&lt;/code&gt; of the lambdas to the respective &lt;code&gt;requirements.txt&lt;/code&gt; files on the &lt;code&gt;cdk_app&lt;/code&gt; project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;projects/cdk_app/
&lt;span class="nb"&gt;cp&lt;/span&gt; ../hello_lambda_project/dist/&lt;span class="k"&gt;*&lt;/span&gt;.whl lambda/hello/
&lt;span class="nb"&gt;cp&lt;/span&gt; ../hitcounter_lambda_project/dist/&lt;span class="k"&gt;*&lt;/span&gt;.whl lambda/hitcounter/
&lt;span class="nb"&gt;cd &lt;/span&gt;lambda/hello/
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; | find &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.whl"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;span class="nb"&gt;cd&lt;/span&gt; ../hitcounter/
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; | find &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.whl"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;span class="nb"&gt;cd&lt;/span&gt; ../../ &lt;span class="c"&gt;# back to projects/cdk_app&lt;/span&gt;
poetry build-project &lt;span class="c"&gt;# need to rebuild since we make changes&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
&lt;span class="c"&gt;# --force-reinstall is necessary unless we change the package version&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--force-reinstall&lt;/span&gt; dist/cdk_app-0.1.0-py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;note: &lt;code&gt;Runtime.PYTHON_3_9.bundling_image&lt;/code&gt; will fail if any of the packages need a greater version of python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can deploy again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# from the projects/cdk_app/ with the python virtual env active&lt;/span&gt;
cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is important to note that most of this process is probably part of the DevOps setup, and rarely you will have to do any of this manually. But hey! it is better to know where things come from and be able to fix it than waiting on somebody else to fix it for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;, the lambdas will fail complaining that they can not find the handler module event if it is included correctly in the lambda package code. For this to work you'll need &lt;code&gt;Runtime.PYTHON_3_9&lt;/code&gt; at least&lt;/p&gt;

&lt;p&gt;Let's add the last &lt;a href="https://github.com/ybenitezf/cdk_polylith/commit/e70193a0c53f4cfd404cc00a1c8a382ce560b541" rel="noopener noreferrer"&gt;checkpoint here and commit our changes&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final considerations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This monorepo methodology makes it easy to start a new project or change an existing one.&lt;/li&gt;
&lt;li&gt;All your repositories will look consistent with the same structure and elements.&lt;/li&gt;
&lt;li&gt;With all the code in the same repository you can detect if something could potentially break other parts of the system even if they are deployed separately.&lt;/li&gt;
&lt;li&gt;Last but not least, there is a clear separation between the code and the deploy artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this article help you improve your coding skills, make your projects more organized and professional, and save you some time in the future.&lt;br&gt;
Go do something fun with that extra time.&lt;/p&gt;

&lt;p&gt;Until the next post,&lt;br&gt;
Take care and happy coding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Acknowledgments
&lt;/h2&gt;

&lt;p&gt;Thanks to Robmay S. Garcia for the review, corrections and help.&lt;/p&gt;

&lt;p&gt;Thanks &lt;a href="https://github.com/DavidVujic" rel="noopener noreferrer"&gt;David Vujic&lt;/a&gt; for this excellent tool.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>python</category>
      <category>polylith</category>
    </item>
  </channel>
</rss>
