Code Monkey home page Code Monkey logo

hassanhabib / the-standard Goto Github PK

View Code? Open in Web Editor NEW
1.0K 65.0 195.0 10.22 MB

This is The Standard. A collection of decades of experience in the engineering industry. I authored it to help you navigate the vast ocean of knowledge. The Standard is not perfect and never will be, and it reflects the ongoing evolution of the engineering industry. While one person may write it, it is the collection of thoughts from hundreds of engineers I've had the honor to interact with and learn from throughout my life.

the-standard's Introduction

The Standard

The Standard The Standard Community

Chat with us here on Discord:

Discord

Other Resources

Translations

The Standard in Different Programming Languages

Projects

the-standard's People

Contributors

altoption avatar aosunlana avatar appsolab avatar ashley-upson avatar boorda avatar ccampora avatar cjdutoit avatar danielle-io avatar dlandi avatar donsn avatar eriadhami avatar evangelinedrink avatar glhays avatar hassanhabib avatar jayendusharma avatar joshmccall221 avatar kandarpgautam avatar lboullosa avatar mtoncic avatar pratikkaje avatar rcruzfreelance avatar rekarpc98 avatar rohitg7 avatar schnickalodeon avatar sd-tang avatar sharaf-mansour avatar shihamsam avatar shrihumrudha avatar stjanovi avatar terrypalo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

the-standard's Issues

Orcherstration Validations

Hi hassan,
I have an interogations.
In your StudentOrchestrationService

public async ValueTask<Student> RegisterStudentAsync(Student student)
{
    Student addedStudent =
        await this.studentProcessingService.AddStudentAsync(student);

    LibraryCard libraryCard = 
        await this.libraryCardPorcessingService.AddLibraryCardAsync(
            addedStudent.Id);

    return addedStudent;
}

If AddStudentAsync call an ApIBroker and if if (student.CodeResponse== "1" or student.CodeResponse== "10")
we dont want to add a librarycard.
We should I put the validations ?

Thx a lot, for you Job !

DOCUMENTATION: Branch and commit naming conventions

Discussed in #225

Originally posted by Sharaf-Mansour January 6, 2023
It should be clear how we name our branches and commits according to the standard
Like a dedicated section for version control to show the true beauty of the standard
(Telling the whole story of the project)

Log

Hi @hassanhabib ,

An another interogations. Maybe you mentionned that but didn't found it.

public async ValueTask<Student> AddStudentAsync(Student student) =>
TryCatch(async () => 
{
    ...
    Student addedStudent = await this.studentService.AddStudentAsync(student);
    LibraryCard libraryCard = await this.libraryCard.AddLibraryCard(addedStudent.Id);

    return addedStudent;  
});

In case of errors into StudentService.
Won't we log twice the same informations ? One time into StudentService then into StudentOrchestrationService.

Thx

DOCUMENTATION: Add FAQ for each chapter

Hi!

Having in mind the Brokers FAQ could be helpful add as many FAQs for each chapter. This will be very useful when start learning The Standard, it could be a good starting point for anyone because I think, in some way, all of us, we always ask same similar questions about integrating components, what could be done or not when integrating components or any other concerns related to design a system according The Standard.

Firstly, I will enumerate a few questions I have, then I will post it here.

If anyone has questions. no matter if they are pretty simple, easy it will be welcomed for sure. Who knows, maybe one of these easy questions may help me or another. It will be great to add them to the documentation.

Thanks Hassan and everyone!

brokers

Hi Hassan,
I'm still in learning curve with "The-Standard".

If I need to generate a studentcard number with some algorithmics without call to any "Entity Brokers" etc...

Usually I would have made a static method like this.
public static string StudentServiceHelpers.GenerateCardReference() { _some logic...._ }
But in your recommandation, you said to avoid helpers etc....
Should I create StudentCardBroker like DateTimeBroker to be in respect with "The-Standard" convention.

StudentCardBroker should be a "support brokers" or a "Entity Brokers" ?

Or maybe I'm completely wrong....

By the way ,
I'm start to present in my compagny "The standard".

Thx a lot !

DOCUMENTATION: The software should be traceable and observable.

There should be a chapter about software engineering traceability and observability topics.

So we have Traces, Metrics, Logs and we have static metadata about our software engineering like issues, stories, epics, bugs, and customer complaints, etc. So the dream is to enrich these types of data by combining them into one traceable graph of data.

Sources of what I'm talking about :
https://opentelemetry.io/ - Traces, Metrics, Logs
https://github.com/backstage/backstage - Metadata of services and API'S.
https://en.wikipedia.org/wiki/Requirements_traceability - Every requirement or story should be back traceable to code
https://zipkin.io/ - Distributed tracing
https://en.wikipedia.org/wiki/Static_program_analysis - Code metadata
https://en.wikipedia.org/wiki/Causal_graph - by having a causality graph you can rigorously answer questions.

Found Typo in 2.1.3.1.5.0

I found a Typo in The-Standard (here)

Below the Unit Tests you wrote AlreadyExcistsStudentException instead of AlreadyExistsStudentException (there is a c)

Btw. Thank you for that awesome standard :)

Orchestration Service Model

@hassanhabib bro, i am trying to implement orchestration service in a project and i have a question. The orchestration layer may live after the exposers and exposesers may introduce new models which will be mapped, so in your opinion do we need to create these new models in Models folder?

Factorisation Idea

Hi,

I tried to factorise Validation And Excpetion Service into a baseService,
And implementation.
I don't know if it could be usefull or if i'm doing wrong.

Keep going to do your video I learned a lot thx to you !

public class BaseService
{
    protected readonly ILog log;

    public delegate ValueTask<T> Delegate<T>();

    public BaseService(ILog log)
    {
        this.log = log;
    }

    public NullException CreateAndLogInvalideException(Xeption exception)
    {
        var nullException = new NullException();
        log.Error(JsonConvert.SerializeObject(exception.Data), exception);
        return nullException;
    }

    public ServiceException CreateAndLogServiceException(Xeption xeption)
    {
        var serviceException = new ServiceException(xeption);
        log.Error(JsonConvert.SerializeObject(xeption.Data), xeption);
        return serviceException;
    }

    public DependencyException CreateAndLogValidationDependencyException(Xeption exception)
    {
        var depenDencyException = new DependencyException(exception);
        log.Error("Dependecy Error", exception.InnerException);
        return depenDencyException;
    }

    public ValidationException CreateAndLogValidationException(Exception exception)
    {
        ValidationException validationException = new ValidationException(exception);
        log.Error(exception.Message);
        return validationException;
    }

    public ValidationException CreateAndLogValidationXeption(Xeption exception)
    {
        ValidationException validationException = new ValidationException(exception);
        log.Error(JsonConvert.SerializeObject(exception.Data), exception);
        return validationException;
    }


    public dynamic IsInvalidX(string text) => new
    {
        Condition = String.IsNullOrWhiteSpace(text),
        Message = "Text is required"
    };

    public dynamic IsInvalidX(DateTime date) => new
    {
        Condition = date == null,
        Message = "Date is required"
    };

    public dynamic IsInvalidX(int value) => new
    {
        Condition = value <= 0,
        Message = "Value is required"
    };

    public dynamic IsInvalidX(decimal value) => new
    {
        Condition = value <= 0,
        Message = "Value is required"
    };

    public dynamic IsInvalidX(long value) => new
    {
        Condition = value <= 0,
        Message = "Value is required"
    };

    public dynamic IsNotNull(object myObject, string objectName) => new
    {
        Condition = myObject != null,
        Message = $"Object : {objectName} already Exist"
    };



    public dynamic IsNullX(object myObject, string objectName) => new
    {
        Condition = myObject is null,
        Message = $"Object : {objectName} can't be null"
    };

    public dynamic IsNullX(object myObject, string objectName, string parameterName, object id) => new
    {
        Condition = myObject is null,
        Message = $"Couldn't find {objectName} with {parameterName}: {id}"
    };

    public async ValueTask<T> TryCatch<T>(Delegate<T> returningDelegate)
    {
        try
        {
            return await returningDelegate();
        }
        catch (InvalidException invalidException)
        {
            throw CreateAndLogValidationXeption(invalidException);
        }
        catch (NotFoundException notFoundException)
        {
            throw CreateAndLogValidationXeption(notFoundException);
        }
        catch (NullException nullContratCarteException)
        {
            throw CreateAndLogValidationXeption(nullContratCarteException);
        }
        catch (OracleException oracleException)
        {
            var failedStudentStorageException =
                new FailedStorageException(oracleException);
            throw CreateAndLogValidationDependencyException(failedStudentStorageException);
        }
        catch (Exception exception)
        {
            var failServiceException =
                new FailedServiceException(exception);
            throw CreateAndLogServiceException(failServiceException);
        }
    }

    public void Validate<T>(params (dynamic Rule, string Parameter)[] validations) where T : Xeption, new()
    {
        var invalidException = new T();

        foreach ((dynamic rule, string parameter) in validations)
        {
            if (rule.Condition)
            {
                invalidException.UpsertDataList(parameter, rule.Message);
            }
        }

        invalidException.ThrowIfContainsErrors();
    }
}

 public sealed class SipsParameterService : BaseService, ISipsParameterService
 {
    private readonly IStorageInMemoryBroker storageInMemoryBroker;


    public SipsParameterService(IStorageInMemoryBroker storageInMemoryBroker)
        : base(LogManager.GetLogger(typeof(SipsParameterService)))
    {
        this.storageInMemoryBroker = storageInMemoryBroker;
    }

    public ValueTask<SipsParameter> GetSipsParametersAsync(string merchantId)
    {
        return TryCatch(async () =>
        {
            ValidateMerchantId(merchantId);
            var parameter = await this.storageInMemoryBroker.GetSipsParametersAsync();
            ValidateParameter(parameter, merchantId);
            return parameter;
        });
    }

    private void ValidateMerchantId(string merchantId)
    {
        Validate<InvalidException>
        (
            (Rule: IsInvalidX(merchantId), nameof(merchantId))

        );
    }

    private void ValidateParameter(SipsParameter parameter, string merchantId)
    {
        Validate<NotFoundException>
        (
            (Rule: IsNullX(parameter, nameof(SipsParameter), nameof(merchantId), merchantId), Parameter: nameof(SipsParameter))
        );
        Validate<InvalidException>
        (
            (Rule: IsInvalidX(parameter.MerchantId), Parameter: nameof(SipsParameter.MerchantId)),
            (Rule: IsInvalidX(parameter.Url), Parameter: nameof(SipsParameter.Url))
        );
    }
}

Commit Convention

hi Hassan, would it be worth adding a commit convention section in the standard? it is not defined properly as to what constitute a fix or a code rub.
My understanding from reading some of the commit histories is that a code rub would just be styling and linting the code and spacing.
Would it cover typos or conventions of plurals and singular or would that fall under a fix?

What would be covered as a fix?

DOCUMENTATION: Add Scenarios & Reasoning for Date Time Validations

Hey everyone,
I'm approving a Standard upgrade proposal to limit date time validations to only 60 seconds in the past so instead of:

        private bool IsDateNotRecent(DateTimeOffset date)
        {
            DateTimeOffset currentDateTime = this.dateTimeBroker.GetCurrentDateTime();
            TimeSpan oneMinute = TimeSpan.FromMinutes(1);
            TimeSpan timeDifference = currentDateTime.Subtract(date);

            return timeDifference.Duration() > oneMinute;
        }

We gonna do:

        private bool IsDateNotRecent(DateTimeOffset date)
        {
            DateTimeOffset currentDateTime = this.dateTimeBroker.GetCurrentDateTime();
            TimeSpan timeDifference = currentDateTime.Subtract(date);

            return timeDifference.TotalSeconds is > 60 or < 0;
        }

credit to Mr. Mendelsohn for this - the reasoning here is that we shouldn't allow a client to post with a date in the future. it should only be in the past within 60 seconds travel time.

Let me know if you have questions.

DOCUMENTATION: Fix some broken links from index page

Hi,
For example I found than exceptions mappings inside Foundations Services isn´t referenced correctly

Referenced from index is
https://github.com/hassanhabib/The-Standard/blob/master/2.%20Services/2.1%20Foundations/2.1%20Foundations.md#21311-exceptions-mappings

But from the actual anchor of the page is

https://github.com/hassanhabib/The-Standard/blob/master/2.%20Services/2.1%20Foundations/2.1%20Foundations.md#21321-exceptions-mappings

I noticed there are many others has the same problem.

I could fix it. Ok?

Thanks!

DOCUMENTATION: Add Dead-End Services

There is no documentation about Dead-End Services.
I asked this on Discord channel,

which name should be the right one for a dead-end service?
Where should be located under the project? ProcessingServices, Foundations.....

Response from @hassanhabib as a brief explanation,

It depends on the type of work that dead-end service does. It can be Processing and it can be Foundation - usually dead-end services tend to do something a bit more advanced so they live in the Processing layers. But every now and then they do something very basic like Add or Subtract in a calculator - they become immediately Foundation.

Request for Repository Review - 'ReserveSpot'

Hi Hassan

Greetings for the day!
Given below are the details about our new repository 'ReserveSpot'. Please review and do the needful.

Description:
Repository ID: 434437163
Name: ReserveSpot
Repo: https://github.com/Mums-Who-Code/ReserveSpot.Services
Description: Playing sports offers many personal, social and health advantages, including the development of esteem and team skills, better overall fitness and increased relationship opportunities. Reserve spot is a sports facility booking platform. Confirmed Bookings, Convenient Process and Cashless Payments with Reserve spot, you enjoy the process of ground booking as much as you enjoy the game.

DOCUMENTATION: SFAL (Standardized Framework Abstraction Library)

  • We need to identify the highest priority items in an existing framework to abstract away:

In terms of higher priority items we are thinking of the following:

  • Most commonly used types (String, IQueryable, List, Exception, Exception ... )
  • Most commonly used routines (ToString(), Streams ...)
  • The Language itself C#?

Another requirement is to be able to create the SDK for The Standard which should provide all these types and routines

image

Concrete examples are needed.

Disclaimer: i might be a potato.

Hi, @hassanhabib !

After reading a good chunk of the Standard, I sense that it has a lot of valuable knowledge, but also I have a feeling that maybe it's a little bit too... abstract? I caught myself being unsure on where would I put even the most common everyday concerns within the model.

I suspect the answers already are in some form in The Standard and my lizard brain is just unable to see or understand them, but I also have a feeling that concrete implementation of the abstraction would help a ton.

To be more specific, below I will provide examples of what I'm confused about, if someone could comment on how to use them within the Standard, it would help me a lot.

Thanks in advance. :)

Examples:

Area Of Confusion: Exceptions
Project: storage API in front of a database.
Scenario: Client tries to save an identity that already exists (e.g. violated some unique constraint, like a book's ISBN). Naturally, I want to return an error to the user with 409 (Conflict).
Ambiguity: In the section about foundation services, it is expected for service to throw an AlreadyExistsException, wraped in DependencyValidationException.
Does this mean that I'm to wrap exceptions like a Russian doll all the way to my controller?
If so, then my controller MUST KNOW the depth of a higher level logic (how many layers of inner exceptions it must traverse before finding that AlreadyExistsException).
Or am I supposed to unwrap the inner exception before rethrowing in higher level services? But what is AlreadyExistsException then? Part of my business logic? If not, Controller will be tightly coupled to foundation, because it MUST KNOW about what exceptions it produces to emit 409.
Side Note: Won't wrapping and re-throwing produce a metric ton of logs that would be equivalent to a stack trace from the 1st thrown exception?

Area Of Confusion: Reliability and Control-flow
Project: External Integration Service
Scenario: We must submit a StudentDto to some external service and it fails or external endpoint challenges us randomly to repeat a request with a computed signature.
Ambiguity: Say I do a request and get HttpRequestException (DNS failed to resolve a host or got a connection reset). Where do I handle it and retry it? I would assume that broker is supposed to handle it, because only it know about networking, but no flow control is allowed. Foundation service? It is not supposed to do anything, but map and validate. Processing service? Wouldn't that expose it to lower level implementation details that were supposed to be abstracted by FS and Broker?
Next level: I get a 500 error from the other side and naturally would like to retry the request. Same questions apply.
Boss level: I get a challenge from the server and need to supply an answer by computing some hash over the initial request model AND a response header. Where should I put this logic and how to I expose necessary details?
Final boss level: Same as boss level, but I am also redirected to another endpoint via 307 and the solution is expected to be retried for this URL, before I am able to call the 1st one.
Side Note: while last 2 cases may seem like I pulled them out of my ass, they are real, albeit much less frequent than first 2.

Area Of Confusion: Scalability
Project: ex-monolith, now distributed system - SchoolControl: student management service, student storage api, library card storage api.
Scenario: I am trying to add a new student and expect it to have a library card. I also expect that library cards exist only for existing students.
Ambiguity: Standard seems like a scalable model, as in you can apply it to a higher order objects (processes, micro services, etc). But it's hard to imagine how that logic would split when we split the app into multiple smaller apps. Where do we put the student validation logic? It sounds like it certainly must be in the student storage api, since it should probably be saving only valid students to DB, but then again, why should it know what a valid student is, when certainly the concept of valid student should be contained in the higher level logic (eg. I'm being told that students must only have mustaches by a school director, not by a storage provider).
Same goes to library card thing. How would a storage know if the student with this id exists? It can't reasonably enforce that constraint, so something else must. But if it can't, what's to prevent a direct call to that api that would make a bogus library card? Do I not have validation in the storage services at all? Do I trust my clients to create proper library cards and only store them?

Some questions about standard.

Hi,
Your work is amazing thank you so much.
I try to read all your content. I have some questions

Brokers 1.2.5 Naming Conventions
If I have a MongoStorageBroker for a student service and SqlStorageBroker for teacherService
So If I understood correctly, I need to implement IMongoStorageBroker ISqlStorageBroker ?

CleanArchitecture
I try to understand.
If I want to implement clean architecture like ardalis https://github.com/ardalis/CleanArchitecture with broker.
In which layer Broker should be put ? The infrastructure layer ?

image

Thanks !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.