Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jezzsantos committed Mar 13, 2024
1 parent 89f1584 commit ea6297a
Show file tree
Hide file tree
Showing 74 changed files with 269 additions and 248 deletions.
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,12 @@ Your Responsibilities are:

* Ensure cross-platform compatibility for every change that's accepted. Windows, Mac, Debian & Ubuntu Linux.
* Ensure that all functional code that goes into SaaStack meets all these requirements
* The change you make compiles, and a final package can still be built from the changed codebase
* You have unit tests and integration tests to demonstrate how the change is working correctly. They must all be run and pass.
* Your code is formatted using the configured formatting/linting tools.
* Your code is self-documenting; the intent of which is easily understandable by other contributors. Comments are not the mechanism to share what the code does, or how, only why.
* Dead code should be removed. Do not include unused commented-out sections of code.
* Your code does not break the build, and passes all checks enforced by GitHub Actions.
* The change you make compiles, and a final package can still be built from the changed codebase
* You have unit tests and integration tests to demonstrate how the change is working correctly. They must all be run and pass.
* Your code is formatted using the configured formatting/linting tools.
* Your code is self-documenting; the intent of which is easily understandable by other contributors. Comments are not the mechanism to share what the code does, or how, only why.
* Dead code should be removed. Do not include unused commented-out sections of code.
* Your code does not break the build, and passes all checks enforced by GitHub Actions.

* Architectural decisions should be discussed with other contributors.
* Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback.
Expand Down
72 changes: 36 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ This starter template is NOT for everyone, nor for EVERY software project, nor f

* The tech stack is a .NET core backend (LTS version 6.0 or later) written in C#, using a few very popular and well-supported 3rd party libraries
* This starter template deliberately makes engineering trade-offs that are optimized for situations where:
1. High maintainability is super important to you (e.g., long-lived codebases)
2. Managing complexity over long periods of time is non-negotiable (~1-10 years), and avoiding big balls of mud (BBOMs) is paramount to you,
3. Where many hands will touch the codebase (i.e., over the course of its entire life)
1. High maintainability is super important to you (e.g., long-lived codebases)
2. Managing complexity over long periods of time is non-negotiable (~1-10 years), and avoiding big balls of mud (BBOMs) is paramount to you,
3. Where many hands will touch the codebase (i.e., over the course of its entire life)

The kinds of '*known scenarios*' that this template is designed specifically for:

Expand All @@ -64,7 +64,7 @@ Can you use this template if your context is different?
Are these trade-offs suitable for any kind of software project?

* No, they are not.
* However, some of them may fit your specific context well.
* However, some of them may fit your specific context well.

> Want to know what the initial design constraints, assumptions, and trade-offs are, then see our [Decisions Log](docs/decisions/README.md) and [Design Principles](docs/design-principles/README.md) for more details on that.
Expand All @@ -76,9 +76,9 @@ It is a starter "template," not a 3rd party library or a fancy 3rd party framewo
* You rename a few things to the name of your product.
* You compile it, you run its tests, and you deploy its pieces into your cloud environment (e.g., Azure, AWS, or Google Cloud).
* You then continue to evolve and add your own features to it (by following the established code patterns). You then evolve and adapt the code to wherever you need it to go.
* Don't like those patterns? then change them to suit your preferences. There are no rigid frameworks or other dev teams to plead with.
* Don't like those patterns? then change them to suit your preferences. There are no rigid frameworks or other dev teams to plead with.
* Read the [documentation](docs/README.md) to figure out what it already has and how things work.
* So that you either don't need to worry about those specific things yet (and can focus on more valuable things), or you can modify them to suit your specific needs. It is your code, so you do as you please to it.
* So that you either don't need to worry about those specific things yet (and can focus on more valuable things), or you can modify them to suit your specific needs. It is your code, so you do as you please to it.

Since this starter "template" is NOT a framework (of the type you usually depend on from others downloaded from [nuget.org](https://nuget.org)), you are free from being trapped inside other people's abstractions and regimes and then waiting on them to accommodate your specific needs. With this template, all you need to do is understand the code, change the code to fit your needs, update the tests that cover it, and move on. Just like you do with all the code you write.

Expand Down Expand Up @@ -107,37 +107,37 @@ It demonstrates a working example of a *made-up* SaaS car-sharing platform just
The starter template also takes care of these specific kinds of things:

* Deployment
* It can be deployed in Azure (e.g., App Services or Functions) or in AWS (e.g., EC2 instances or Lambdas)
* It is designed to be split into as many deployable pieces as you want when needed. (You simply replace the "RPC adapters" with "HttpClient adapters").
* It can be deployed in Azure (e.g., App Services or Functions) or in AWS (e.g., EC2 instances or Lambdas)
* It is designed to be split into as many deployable pieces as you want when needed. (You simply replace the "RPC adapters" with "HttpClient adapters").
* REST API
* It defines a ruleset about how JSON is represented on the wire and how requests are deserialized (to cope with different client styles)
* It localizes developer errors
* It handles and maps common exceptions to standard HTTP status codes
* It returns standard HTTP statuses for successful requests based on the HTTP method (e.g., GET = 200, POST = 201, PUT = 202, DELETE = 204)
* Provides a Swagger UI.
* It defines a ruleset about how JSON is represented on the wire and how requests are deserialized (to cope with different client styles)
* It localizes developer errors
* It handles and maps common exceptions to standard HTTP status codes
* It returns standard HTTP statuses for successful requests based on the HTTP method (e.g., GET = 200, POST = 201, PUT = 202, DELETE = 204)
* Provides a Swagger UI.
* Infrastructure
* All infrastructure components are independently testable adapters
* It implements multi-tenancy for inbound HTTP requests (e.g., HTTP Host headers, URL keys, etc.)
* It implements multi-tenancy (for data segregation) using either data partitioning, physical partitioning, or both.
* It implements polyglot persistence, so you can use whatever persistence technology is appropriate for each module per data load (e.g., SQLServer, Postgres, Redis, DynamoDB, Amazon RDS, LocalFile, In-Memory, etc.)
* It integrated 3rd party identity providers for authentication, 2FA, SSO, and credential management (e.g., Auth0, Microsoft Graph, Google, Amazon Cognito, etc.).
* It integrates billing subscription management providers so that you can charge for your product use and determine feature sets based on subscription levels (e.g., Stripe, ChargeBee, Chargify, etc.).
* It integrates feature flagging providers to control how to access your features and roll them out safely (e.g., LaunchDarkly, GitLab, Unleashed, etc.)
* It integrates product usage metrics to monitor and measure the actual usage of your product (e.g., MixPanel, Google Analytics, Application Insights, Amazon XRay, etc.)
* It integrates crash analytics and structured logging so you can plug in your own preferred monitoring (e.g., Application Insights, CloudWatch, Sentry.io, etc.).
* It uses dependency injection extensively so that all modules and components remain testable and configurable.
* It defines standard and unified configuration patterns (e.g., using `appsettings.json`) to load tenanted or non-tenanted runtime settings.
* All infrastructure components are independently testable adapters
* It implements multi-tenancy for inbound HTTP requests (e.g., HTTP Host headers, URL keys, etc.)
* It implements multi-tenancy (for data segregation) using either data partitioning, physical partitioning, or both.
* It implements polyglot persistence, so you can use whatever persistence technology is appropriate for each module per data load (e.g., SQLServer, Postgres, Redis, DynamoDB, Amazon RDS, LocalFile, In-Memory, etc.)
* It integrated 3rd party identity providers for authentication, 2FA, SSO, and credential management (e.g., Auth0, Microsoft Graph, Google, Amazon Cognito, etc.).
* It integrates billing subscription management providers so that you can charge for your product use and determine feature sets based on subscription levels (e.g., Stripe, ChargeBee, Chargify, etc.).
* It integrates feature flagging providers to control how to access your features and roll them out safely (e.g., LaunchDarkly, GitLab, Unleashed, etc.)
* It integrates product usage metrics to monitor and measure the actual usage of your product (e.g., MixPanel, Google Analytics, Application Insights, Amazon XRay, etc.)
* It integrates crash analytics and structured logging so you can plug in your own preferred monitoring (e.g., Application Insights, CloudWatch, Sentry.io, etc.).
* It uses dependency injection extensively so that all modules and components remain testable and configurable.
* It defines standard and unified configuration patterns (e.g., using `appsettings.json`) to load tenanted or non-tenanted runtime settings.
* Application
* Supports one or more applications, agnostic to infrastructure interop (i.e., allows you to expose each application as a REST API (default) or as a reliable Queue, or any other kind of infrastructure)
* Supports transaction scripts + anemic domain model or Domain Driven Design
* Applications are aligned to audiences and subdomains
* Supports one or more applications, agnostic to infrastructure interop (i.e., allows you to expose each application as a REST API (default) or as a reliable Queue, or any other kind of infrastructure)
* Supports transaction scripts + anemic domain model or Domain Driven Design
* Applications are aligned to audiences and subdomains
* Others
* It provides documented code examples for the most common use cases. Simply follow and learn from the existing patterns in the codebase
* It provides a [decision log](docs/decisions/README.md) so you can see why certain design decisions were made.
* It provides documentation about the [design principles](docs/design-principles/README.md) behind the codebase so you can learn about them and why they exist.
* It \[will\] provide an eco-system/marketplace of common adapters that other people can build and share with the community.
* It demonstrates extensive and overlapping testing suites (unit tests, integration tests, and end-to-end tests) to ensure that production support issues are minimized and regressions are caught early on. As well as allowing you to change any of the existing base code safely
* It defines and enforces coding standards and formatting rules
* It utilizes common patterns and abstractions around popular libraries (that are the most up-to-date in the .NET world), so you can switch them out for your preferences.
* It defines horizontal layers and vertical slices to make changing code in any component easier and more reliable.
* It enforces dependency direction rules so that layers and subdomains are not inadvertently coupled together (enforcing architectural constraints)
* It provides documented code examples for the most common use cases. Simply follow and learn from the existing patterns in the codebase
* It provides a [decision log](docs/decisions/README.md) so you can see why certain design decisions were made.
* It provides documentation about the [design principles](docs/design-principles/README.md) behind the codebase so you can learn about them and why they exist.
* It \[will\] provide an eco-system/marketplace of common adapters that other people can build and share with the community.
* It demonstrates extensive and overlapping testing suites (unit tests, integration tests, and end-to-end tests) to ensure that production support issues are minimized and regressions are caught early on. As well as allowing you to change any of the existing base code safely
* It defines and enforces coding standards and formatting rules
* It utilizes common patterns and abstractions around popular libraries (that are the most up-to-date in the .NET world), so you can switch them out for your preferences.
* It defines horizontal layers and vertical slices to make changing code in any component easier and more reliable.
* It enforces dependency direction rules so that layers and subdomains are not inadvertently coupled together (enforcing architectural constraints)
6 changes: 3 additions & 3 deletions README_DERIVATIVE.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,10 @@ To kill these processes:
* Find the processes: `lsof -Pni | grep "5001\|5101\|5656"`
* Kill the processes: `kill -9 <processid>` where `<processid>` is the ID of the process in the list
* Alternatively, in MacOS:
* Alternatively, in MacOS:
* Use `lsof -ti :[PORT]` and locate the PID of the process, e.g., `lsof -ti :5656`.
* Open "Activity Monitor", locate the process with that PID, and stop that process.
* Use `lsof -ti :[PORT]` and locate the PID of the process, e.g., `lsof -ti :5656`.
* Open "Activity Monitor", locate the process with that PID, and stop that process.
## Testing The Code
Expand Down
2 changes: 1 addition & 1 deletion docs/design-principles/0030-recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,6 @@ To work around this problem, the JavaScript application can instead relay that t

Again, the `WebsiteHost` can provide the relay mechanism, but the data capture part (in the browser) still is best performed in JavaScript.

> It is technically feasible to use the vendor's SDKs to capture the data in the browser, but instead of relaying it to the 3rd party cloud endpoints, direct it to the BEFFE recorder API to relay.
> It is technically feasible to use the vendor's SDKs to capture the data in the browser, but instead of relaying it to the 3rd party cloud endpoints, direct it to the BEFFE recorder API to relay.
>
> For example, when using the Application Insights JavaScript SDK, you can overwrite the `endpointUrl` to point to your own BEFFE. Then, standup a custom API (in the BEFFE) that looks like the Application Insights API in Azure, and then translate the data that the `HostRecorder` can forward onto Application Insights itself. See: https://github.com/shaneochotny/ApplicationInsights-JS-Proxy for more details.
2 changes: 1 addition & 1 deletion src/AncillaryDomain.UnitTests/EmailDeliverRootSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public void WhenSucceededDelivery_ThenDelivered()
root.Delivered.Should().BeNear(DateTime.UtcNow);
root.Events.Last().Should().BeOfType<Events.EmailDelivery.DeliverySucceeded>();
}

private static QueuedMessageId CreateMessageId()
{
var messageId = new MessageQueueIdFactory().Create("aqueuename");
Expand Down
18 changes: 9 additions & 9 deletions src/AncillaryInfrastructure/Api/FeatureFlags/FeatureFlagsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ public async Task<ApiGetResult<FeatureFlag, GetFeatureFlagResponse>> Get(GetFeat
return () => flag.HandleApplicationResult(f => new GetFeatureFlagResponse { Flag = f });
}

public async Task<ApiGetResult<FeatureFlag, GetFeatureFlagResponse>> GetForCaller(
GetFeatureFlagForCallerRequest request,
public async Task<ApiGetResult<List<FeatureFlag>, GetAllFeatureFlagsResponse>> GetAll(
GetAllFeatureFlagsRequest request,
CancellationToken cancellationToken)
{
var flag = await _featureFlagsApplication.GetFeatureFlagForCallerAsync(_contextFactory.Create(),
request.Name, cancellationToken);
var flags = await _featureFlagsApplication.GetAllFeatureFlagsAsync(_contextFactory.Create(), cancellationToken);

return () => flag.HandleApplicationResult(f => new GetFeatureFlagResponse { Flag = f });
return () => flags.HandleApplicationResult(f => new GetAllFeatureFlagsResponse { Flags = f });
}

public async Task<ApiGetResult<List<FeatureFlag>, GetAllFeatureFlagsResponse>> GetAll(
GetAllFeatureFlagsRequest request,
public async Task<ApiGetResult<FeatureFlag, GetFeatureFlagResponse>> GetForCaller(
GetFeatureFlagForCallerRequest request,
CancellationToken cancellationToken)
{
var flags = await _featureFlagsApplication.GetAllFeatureFlagsAsync(_contextFactory.Create(), cancellationToken);
var flag = await _featureFlagsApplication.GetFeatureFlagForCallerAsync(_contextFactory.Create(),
request.Name, cancellationToken);

return () => flags.HandleApplicationResult(f => new GetAllFeatureFlagsResponse { Flags = f });
return () => flag.HandleApplicationResult(f => new GetFeatureFlagResponse { Flag = f });
}
}
8 changes: 4 additions & 4 deletions src/Application.Interfaces/ICallerContext.RolesAndFeatures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public CallerRoles(RoleLevel[]? platform, RoleLevel[]? tenant)

public RoleLevel[] All { get; }

public RoleLevel[] Tenant { get; }

public RoleLevel[] Platform { get; }

public RoleLevel[] Tenant { get; }
}

/// <summary>
Expand All @@ -58,8 +58,8 @@ public CallerFeatures(FeatureLevel[]? platform, FeatureLevel[]? tenant)

public FeatureLevel[] All { get; }

public FeatureLevel[] Tenant { get; }

public FeatureLevel[] Platform { get; }

public FeatureLevel[] Tenant { get; }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Application.Interfaces.Resources;

/// <summary>
/// Defines a resource that has a unique identifier
/// Defines a resource that has a unique identifier
/// </summary>
public interface IIdentifiableResource
{
Expand Down
4 changes: 2 additions & 2 deletions src/Application.Resources.Shared/EndUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ public class Membership : IIdentifiableResource
{
public List<string> Features { get; set; } = new();

public bool IsDefault { get; set; }

public required string OrganizationId { get; set; }

public List<string> Roles { get; set; } = new();

public required string Id { get; set; }

public bool IsDefault { get; set; }
}
1 change: 0 additions & 1 deletion src/CarsDomain/CausedBy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public static Result<CausedBy, Error> Create(UnavailabilityCausedBy reason, Opti
{
return error2;
}

}

return new CausedBy(reason, reference);
Expand Down
Loading

0 comments on commit ea6297a

Please sign in to comment.