✔️ Giriş
✔️ Temiz Mimari nedir ve buna neden ihtiyacımız var?
✔️ Sunucusuz Yaklaşım
✔️ Yapbozun temel parçaları
✔️ Neden bu yaklaşımı kullanmalıyım?
✔️ Sarma
Yazının 2. bölümüne buradan ulaşabilirsiniz:Etki Alanına Dayalı Tasarımla Sunucusuz Temiz Mimari ve Kod — 2. Bölüm
Daha ileri gitmeden önce — gelecekteki blog gönderileri ve Sunucusuz haberler için lütfen LinkedIn'de benimle bağlantı kurunhttps://www.linkedin.com/in/lee-james-gilmore/
Bu makalede, hayali şirketimiz " Onion Sounds — Lee James Online Sound Studio " için bir uygulama oluşturacağız ve Sunucusuz çözümlerinizi genellikle " temiz ", " altıgen " veya " onion " mimarileri olarak adlandırılan yapılandırmanın bir yolunu göstermemize olanak tanıyacağız. ; işlevsel programlama ve etki alanı güdümlü tasarım, yani DDD ile Sunucusuz ve TypeScript Dünyasındaki deneyime dayanmaktadır.
Bu mimari yaklaşımın avantajlarını ve nedenlerini de yazı boyunca tartışacağız.
Yaklaşımdan bahsetmek için TypeScript ve CDK kullanarak aşağıdaki küçük uygulamayı oluşturacağız:
Diyagramdaki akış aşağıdaki gibidir:
CreateAccountMüşteri, AWS Lambda işlevimizi çağıran API aracılığıyla bir hesap oluşturabilir .
CustomerAccountUpgraded' etkinliği yayınlanır. ( Oluşturulan Müşteri Hesabı ile aynı — kısa olması için şemadan kaldırıldı )
Bu makaleyi , birkaç hafta önce yaptığım bir LinkedIn anketine dayanarak yazdım ; burada oy kullananların yalnızca %30'u şu anda benzer bir yaklaşımı ( soğan/altıgen/temiz ) kullanıyor ve neredeyse yine aynı yaklaşım ( %29 ) ne olduğunu bile bilmiyor . onlar. Ayrıca birçok kuruluşta, ölçekte birçok soruna yol açan yetersiz kod soyutlaması görüyorum ( aşağıda daha ayrıntılı olarak açıklanmıştır ):
Tamam, o halde önce Clean , Hexagonal ve Onion mimarileri ile benzerliklerin neler olduğunu ve günümüzün Sunucusuz işletmelerinde bu yaklaşımlara neden ihtiyaç duyduğumuzu inceleyerek başlayalım.
Tartışacağımız bu farklı yaklaşımların her biri varlığa odaklanma :
✔️ Çerçevelerden Bağımsız . Mimari, özellik yüklü bir yazılım kitaplığının varlığına bağlı değildir. Bu, sisteminizi sınırlı kısıtlamalarına sıkıştırmak yerine, bu tür çerçeveleri araç olarak kullanmanıza olanak tanır.
✔️ Test edilebilir . İş kuralları, Kullanıcı Arabirimi, Veritabanı, Web Sunucusu veya başka herhangi bir harici öğe olmadan test edilebilir.
✔️ Kullanıcı arayüzünden bağımsız . Kullanıcı arabirimi, sistemin geri kalanını değiştirmeden kolayca değişebilir. Bir Web kullanıcı arayüzü, örneğin iş kurallarını değiştirmeden bir konsol kullanıcı arayüzü ile değiştirilebilir.
✔️ Veritabanından Bağımsız . Oracle veya SQL Server'ı Mongo, BigTable, CouchDB veya başka bir şeyle değiştirebilirsiniz. İş kurallarınız veri tabanına bağlı değildir.
✔️ Herhangi bir dış kurumdan bağımsız . Aslında iş kurallarınız dış dünya hakkında hiçbir şey bilmiyor.
Bu yaklaşımların her birini şimdi aşağıda yüksek bir düzeyde bağımsız olarak ele alalım.
Altıgen Mimari, Wikipedia tarafından şu şekilde tanımlanmaktadır:
" Altıgen mimari veya bağlantı noktaları ve bağdaştırıcı mimarisi , yazılım tasarımında kullanılan bir mimari modeldir . Bağlantı noktaları ve adaptörler aracılığıyla yazılım ortamlarına kolayca bağlanabilen gevşek bağlı uygulama bileşenleri oluşturmayı amaçlar . Bu, bileşenleri herhangi bir seviyede değiştirilebilir hale getirir ve test otomasyonunu kolaylaştırır” —https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)
Bu ilk olarak 2005 yılında Alistair Cockburn tarafından icat edildi . Bu yaklaşımın altı tarafı olması gerekmediğinden, birçok kişi buna " Altıgen Mimariler " yerine " Bağlantı Noktaları ve Adaptörler " demeyi sever; ancak yalnızca birden çok bağdaştırıcıyı ve iki taraf arasındaki farkı göstermek için kullanıldı.
Bu modelin temel dayanağı, teknolojiden bağımsız olan temel iş alanımız ile teknoloji ( veritabanları, kullanıcı arabirimi, API'ler vb .)
2008 yılında Jeffery Palermo, aşağıdaki makalede 'Onion Architectures' mimari modelini ortaya attı .
Jeffrey Palermo tarafından 2008'de önerilen soğan mimarisi, altıgen mimariye benzer: ayrıca, uygulama ile veri tabanı arasında gevşek bağlantı sağlamak için altyapıyı arabirimlerle dışsallaştırır . Kontrolün ters çevrilmesini kullanarak uygulama çekirdeğini birkaç eşmerkezli halkaya ayrıştırır .” — Vikipedi
Temel kural, tüm kodun daha merkezi katmanlara bağlı olabileceği, ancak kodun çekirdekten daha uzaktaki katmanlara bağlı olamayacağıdır. Başka bir deyişle, tüm bağlantı merkeze doğrudur. Bu mimari utanmadan nesne yönelimli programlamaya eğilimlidir ve nesneleri diğerlerinin önüne koyar.
Son olarak, Robert "Bob Amca" Martin, 2012'de aşağıdaki gönderide Temiz Mimarilerden bahsetti .
“ 2012'de Robert C. Martin tarafından önerilen temiz mimari , altıgen mimarinin, soğan mimarisinin ve diğer birkaç değişkenin ilkelerini birleştiriyor; Eşmerkezli halkalar olarak sunulan, bileşene ilişkin ek ayrıntı düzeyleri sağlar. Bağdaştırıcıları ve arabirimleri (kullanıcı arabirimi, veritabanları, harici sistemler, cihazlar) mimarinin dış halkalarında izole eder ve iç halkaları kullanım durumları ve varlıklar için bırakır . Temiz mimari, bağımlılığın tersine çevrilmesi ilkesini, bağımlılıkların yalnızca bir dış halka ile bir iç halka arasında var olacağı ve asla tersinin olmayacağı şeklindeki katı kuralla kullanır. ” — Vikipedi
"Uygulama Servislerini" "Kullanım Durumları" olarak değiştirerek ve "Etki Alanı Modeli"nin yerini, Kuruluş genelindeki iş kurallarını oluşturan "Varlıklar" ile değiştirerek, diğer yaklaşımların üzerinde bir model olarak inşa edilir.
Bir uygulamanın veya mikro hizmetin ne yaptığının hızlı bir bakışta son derece açık olması gerektiği öncülüyle, büyük bir hayranı olduğum ' Screaming Architectures ' kavramı da tanıtıldı.
Aşağıdaki diyagram, ilerlerken ayrıntılı olarak tartışacağımız Sunucusuz ve TypeScript Dünyasındaki yaklaşımımı gösteriyor ve bunu ilerledikçe örneğimize ve kod depomuza geri bağlıyoruz. Bu, büyük ölçüde yukarıdaki önceki yaklaşımlara dayanmaktadır, ancak Sunucusuz ve TypeScript Dünyası için:
Bu nedenle, yukarıdaki diyagramı ve Sunucusuz Dünya'da buna neden ihtiyacımız olduğunu tartışmaya başlamadan önce, kurumsal organizasyonlarda bir karşılaştırma olarak tipik olarak ne gördüğüme bakalım:
Yukarıdaki şemada, kodumuz ve altyapımız etrafında herhangi bir ayrımın olmadığını görebiliriz ve bireysel Lambda işlevlerimiz, iş mantığı, işleyici kodu, istek ve yanıt eşleme ve daha fazlası için çöplük alanı haline gelir.. bunu aşağıda görelim. gerçek kod olarak:
Bu oldukça tipik örnekten de görebileceğimiz gibi ( yukarıdaki koddaki yorumlar ), bir dosyada dört tür koda sahibiz :
❌ Lambda işlev işleyici kodu.
❌ AWS harici hizmetler kodu.
❌ Sipariş oluşturmak ve doğrulamak için etki alanı mantığı.
❌ Dosyalara dağılmış ortam değişkenleri.
Yukarıdaki tipik örneğe dayanarak şunları buluyoruz:
❌ Bu kadar hizmetle alay ettiğimiz için kodu test etmekte zorlanıyoruz.
❌ Kod çok kırılgan ve bakımı zor.
❌ Birçok fonksiyonda çok fazla kod çoğaltmamız var.
❌ Etki alanı mantığı birçok işlev arasında sızdırıyor.
❌ Ve tam bir yeniden yazma olmadan bu uygulamayı kapsayıcılara veya eşdeğerine taşımakta zorlanırdık.
"Bu sadece bir işlev.. şimdi bunu kuruluşunuzdaki yüzlerce/binlerce işlevle çarpın.. Ah!"
Daha sonra bunu bir kuruluş genelinde tahmin edersek, iş mantığımızın daha sonra sayısız işleve dağıldığını ve seyreldiğini görebiliriz ( etki alanı mantığı, her lambda içindeki yeşil dairelerdir ):
O halde bu işlevlerden yüzlerce hatta binlercesine sahip olabileceğiniz görüşünü alırsanız , o zaman bir sorununuz var demektir! Etki alanı mantığınız kuruluşunuzun neresinde?
"Domain mantığınız kuruluşunuzun neresinde?"
Bir sonraki bölümde yapbozun bazı önemli parçalarını ele alalım.
Now let’s talk through the main pieces of the puzzle based on the diagram below, and see how a specific folder structure can support this in our TypeScript solutions:
We can see the flow of the service in the diagram which shows:
Primary Adaptertakes the input and forwards to our
Use Casewhich is devoid of any technical implications (no notion of Lambda for example in our Use Case)
Use Caseis our main business logic flow, for example creating a customer account; which interacts with our
domain entities(CustomerAccount).
Use Casesarayın .
Repositories
repositoriesbağımsızdırlar ve
secondary adaptersbelirli teknolojilerle etkileşim kurmak için etkileşime girerler.
secondary adaptersdurumumuz, oluşturulan hesapları DynamoDB'de depolamak ve olayları Amazon EventBridge'de yayınlamak içindir. Bunlar elbette teknolojinin farkında.
Her işletme mikro hizmeti veya Sınırlı Bağlam için bir zengin etki alanı modeli tanımlayın .
Etki Alanı Modeli ( Etki Alanı Hizmeti ), etki alanındaki ( bizim örneğimizde Müşteri Hesabı etki alanı ) soruna ilişkin yapılandırılmış bilginizdir .
Etki Alanı Modeli, problem alanının temel kavramlarını temsil etmeli ve alan kapsamındaki tüm varlıklar arasındaki ilişkileri tanımlamalıdır. Etki Alanı Modeli, tipik olarak , mikro hizmetinizin sınırlı bağlamıyla bire bir eşlemedir .
Yukarıdaki şemadan da görebileceğimiz gibi, genel Etki Alanı Hizmeti, Kullanım Durumlarını ve Depoları da içerir, ancak dışarıda oturdukları şekliyle bağdaştırıcıları içermez ( buna daha sonra değineceğiz ).
Aşağıdaki ekran görüntüsünden, Sunucusuz mikro hizmet genel uygulamamızı yukarıdaki şemadakiyle eşleşen aşağıdaki klasörlerde modellediğimizi görebiliriz, bu da birçok depoda ortak bir yaklaşım olarak akıl yürütmeyi kolaylaştırır:
Bu özel klasör yapısı, etki alanı hizmetlerimiz ve organizasyonumuz genelinde tutarlılığın sağlanmasına yardımcı olur ve hizmetlerimizi doğru düzeyde soyutlama ile oluşturmamızı sağlar.
Etki Alanı Modeli özeti
✔️ Genel etki alanı hizmetimiz için sınırlı bir bağlamdır.
✔️ Etki Alanı Varlıkları, Kullanım Durumları ve Depolardan oluşur.
"Öncelikle kimliğiyle tanımlanan bir nesneye Varlık denir." — Eric Evans
Varlıklar, bir modelin temelini oluşturdukları için etki alanı modelinde çok önemlidir. Etki alanı varlıkları, uygulamamız içindeki ' müşteri hesabı ', ' fatura ' veya ' ödeme ' gibi kavramları oluşturan iş nesneleridir . Bunlar , etki alanı modelinizde/uygulamanızda herhangi bir iş mantığı için ilk bağlantı noktası olmalıdır .
"Nesnelerimizin geçersiz bir duruma düşmesini asla istemiyoruz."
Basitçe POCO sınıfları ( alıcılar ve ayarlayıcılar ) olan anemik etki alanı varlıkları yerine, kendilerine uygun belirli iş mantığına sahip zengin etki alanı varlıklarına sahip olduğumuzdan emin olmamız gerekir . Bu, Martin Fowler tarafından aşağıda tartışılmaktadır:
"Davranışa baktığınızda işin püf noktası ortaya çıkıyor ve bu nesnelerde neredeyse hiç davranış olmadığını fark ediyorsunuz, bu da onları bir çanta dolusu alıcı ve ayarlayıcıdan biraz daha fazlası yapıyor." —Martin Fowler .
Tüm etki alanı varlıklarımızı, testlerinin yanında "etki alanı" klasöründe saklıyoruz:
Uygulamamızdaki bir örnek, birisi hesabı yükseltmeye çalıştığında aşağıdaki gibi her zaman geçerli olması gereken belirli iş kurallarına sahip olabilecek Müşteri Hesabı varlığımız ( yukarıdaki klasör yapısında gösterildiği gibi ) olabilir:
// only allow an upgrade if the payment status is valid if (instance.props.paymentStatus === PaymentStatus.Invalid) { throw new ValidationError('Payment is invalid - unable to upgrade'); }
const instance: CustomerAccount = new CustomerAccount(customerAccountProps); instance.validate(schema);
Etki alanı modelimizi ve varlıklarımızı oluştururken kilit noktalardan biri, genellikle ' Kalıcılık Cehaleti ' olarak bilinen süreklilik konusunda bilgisiz olmamızdır .
'Müşteri Hesabı' varlığımızın koduna bakarsak, kalıcılık veya teknolojiye özgü bir kod görmeyiz, yalnızca saf iş mantığı görürüz. Tek güvendiğimiz türler, hatalar, şema ( varlığın her zaman geçerli olmasını sağlamak için ) ve soyut temel varlıktır:
Etki alanınızı yalnızca veri kalıcılığına göre değil, iş davranışı ve kavramlarına göre modellemek çok daha önemlidir. DDD basitçe, etki alanı modellemenin önce geldiğini ve modellenen verilerin kalıcılığının daha sonra geldiğini söyler.
Etki Alanı Varlığı özeti
✔️ Alanımızı oluşturan işlevselliğin özüdürler.
✔️ Bu varlıklar, kendilerine uygun belirli etki alanı mantığına sahiptir.
️✔️ Teknoloji ve çerçeveden bağımsızdırlar.
✔️ Bunlara yalnızca Birincil Kullanım Durumları aracılığıyla erişilir.
✔️ Her zaman geçerli bir durumdadırlar.
✔️ Herhangi bir iş mantığı için ilk uğrak noktasıdır.
Altıgen Mimariler söz konusu olduğunda, iki temel tanımımız var; soldaki
Drivingtaraf ( veya etkileşimi başlatan birincil aktörler ) ve
Drivensağdaki taraf ( başlatmanın arkasından bir eylem gerçekleştiren ikincil aktörler ).
Örneğimizde,
Driving
Adapterkullanıcı yükü ve yol parametrelerini alıp teknolojiden bağımsız teknolojiye ileten Lambda ile API ağ geçidi etkileşimidir.
Use Case.
DrivenÖrneğimizdeki aktör, verileri almak veya DynamoDB tablomuza göndermek için çağrılan
Adapterveritabanıdır .
repositoryAyrıca etkinlikleri yayınlayabilmek için for Amazon EventBridge'i
repositorykullanır .
Adapter
Kullanım durumları, kullanıcı hikayelerini kodlamak için haritalandırır, çalışma birimleridir (kendi testleriyle kendi dosyalarında yaşamalıdır) ve BDD için başlıca adaylardır.
Use Cases can interact with one or more entities, and will no doubt contain the business logic for the given use case (over and above the entity specific logic of course). Use cases are shown below from the book ‘Clean Architecture’ and how they are documented:
In our specific example we have ‘create a customer account’, ‘retrieve a customer account’, and ‘upgrade a customer account’. Their names should always start with a verb, and they describe the
use cases which make up our overall domain service. Our Use Cases live in the following directory:
Use Cases also deal with the Request and Response models for the Adapters which consume them (shown in green below).
A
Use Case allows any external system or user to interact with our application code via an ‘Adapter’, regardless of what that system is, i.e. technology agnostic.
Use Cases should have no notion of the outside world and how they have been invoked via an adapter (i.e. no notion of specific technologies such as Lambda, API Gateway, DynamoDB etc). Use cases should be pure and deterministic, with any side effects happening in the adapters (in our example the API Gateway adapter).
If we find that we have technical details or implementations in our use cases then we have failed with our adapters!
We can see the code for one of our use cases ‘create customer account’ below:
You can see from the code example above that we are annotating our Use Cases in the same way as Bob C Martin does in his book, which allows us to generate documentation from code using TypeDoc automatically (docs/documentation/index.html). See below:
This facilitates our requirement also for ‘Screaming Architectures’ as it is very apparent to any stakeholder the functionality of our Domain Service through its Use Case documentation, or simply by looking at the use cases folder.
Use Case summary
✔️ They are the basis for our functionality which makes up our domain.
✔️ They are technology and framework agnostic.
✔️ They are only interacted with through primary adapters.
✔️ They interact with repositories for side effects (storing of data, raising events etc).
✔️ If we find that we have technical details or implementations in our use cases then we have failed with our adapters.
We talked about Use Cases above, but now let’s cover their equivalents on the driven side,
repositories.
Repositories are very similar to use cases in as much as they are an abstraction between the domain and the technology (in our case DynamoDB and EventBridge), and they are only ever called via a Use Case or potentially a Domain Entity. This is shown below:
Due to the abstraction of using
Repositories in our clean code we can easily swap out one database technology for another by plugging in a different adapter specific to that database technology, without having to change any other code.
Repositories summary
✔️ They never have any business logic, and they are purely the glue code abstraction between the Use Case and the Adapters.
✔️ Allows us to very quickly and easily swap out technologies or frameworks, for example DynamoDB for DocumentDB, just by swapping out the Adapter.
“No domain logic is present in an adapter; its only responsibility is a technical transformation between the external world and the domain” — InfoQ.
A
Primary Adapter will take the interaction from the technology or framework and interact with the domain code through a
Use Case. In this way the
Use Case has no notion of who or what is communicating with it, and keeps the architecture and code loosely coupled. We store both our Primary and Secondary adapters in the folder structure below:
In our example our
Primary Adapter would specifically be for Lambda, taking in and validating the inputs before calling our
Use Case.
“Adapters are the glue between components and the outside world. They tailor the exchanges between the external world and the ports that represent the requirements of the inside of the application component. There can be several adapters for one Use Case, for example, data can be provided by a user through a GUI or a command-line interface, by an automated data source, or by test scripts.”
This means that a
Use Case can have many different primary adapters to allow different services to interact with our application. We can see the code below for our primary adapter:
This means we could very easily port some domain functionality from API Gateway and Lambda to EventBridge, SNS or SQS event.
We can now look at the
Secondary Adapter which talks to DynamoDB via a repository:
Adapters summary
✔️ They never have any business logic, and they are purely technical for the given actor or consuming service.
✔️ They must confine to the method signature of the Use Case or Repository.
✔️ They allow us to very easily swap out adapters for others which work with different frameworks or technologies.
One of the key tenants of Hexagonal Architectures and Clean Architectures are Dependency Injection (DI) and IoC (Inversion of Control) using Interfaces; however in the Serverless World with AWS Lambda Functions this seems overkill in my opinion, especially due to some of the limitations with TypeScript (more below).
Why do I say this?
Well, we need to find the sweet spot between abstraction upon abstraction and dependency injection/IoC containers at the root of the application entry point (doing all of the wiring up of interfaces to concrete classes), vs the beauty of Serverless which is its speed and simplicity.
My main concern is ensuring that technology specifics are abstracted away from the domain logic to the outer parts of the applications through abstractions (adapters), and that any adapter can plug into our use cases and repositories as long as they confine to the method signatures. I also want to ensure the adapters which are working with frameworks or technologies have no notion of business rules (no business logic leak!). We need to keep them totally separate, and this approach allows for that.
Inversion of Control/DI specific code
Ayrıca, TypeScript'te DI paketi dekoratörlerinin kodun kendisinde serpiştirilmiş ' @injectable ' , ' @injected ' vb. işlev tabanlı yerine tabanlı dosyalar ( çok sayıda korkunç geçici çözüm olmadan ). Sınıf tabanlı programlama için InversifyJS çerçevesinden bir örnek aşağıda gösterilmiştir:
@injectable() class Katana implements Weapon { public hit() { return "cut!"; } } @injectable() class Ninja implements Warrior { private _katana: Weapon; private _shuriken: ThrowableWeapon; public constructor( @inject(TYPES.Weapon) katana: Weapon, @inject(TYPES.ThrowableWeapon) shuriken: ThrowableWeapon ) { this._katana = katana; this._shuriken = shuriken; } public fight() { return this._katana.hit(); }; public sneak() { return this._shuriken.throw(); }; }
Gelecekteki işlevlerle mümkün olsa bile, bu çerçeveye özgü kodu mikro hizmetime katıştırmak istemiyorum.
TypeScript İşlevsel Programlama ve OOP
Ayrıca TypeScript ile Sunucusuz Dünya'da, çoğu çözümün Nesne Yönelimli ( OOP ) üzerinden işlevsel bir programlama yaklaşımı kullanılarak oluşturulduğunu ve TypeScript'teki bağımlılık enjeksiyon çerçevelerinin, dekoratör sınırlamaları nedeniyle (yalnızca sınıflar) işlevlerle ( yalnızca sınıflar ) iyi çalışmadığı bilinir. aşağıdaki bağlantıya bakın ).
Belgelenen bu yaklaşım, kurumsal bir bakış açısından, Typed Inject, InversifyJS ve diğerleri gibi ek çerçeveler kurmadan ve DDD'yi göz önünde bulundurarak uyum sağlama ve büyüme için kendimizi doğru şekilde kurduğumuzdan emin olmaktır.
İşlevleri sınıflara dönüştürmek için örnek repoyu kullanmaktan çekinmeyin ve isterseniz Inversify veya benzer bir çerçeve kullanarak kontrolün ve DI'nin ters çevrilmesini uygulayın, isterseniz bunu yapması çok kolaydır.
Özet
✔️ TypeScript'teki ana DI/IoC çerçeveleri için dekoratörler yalnızca sınıflarla çalışır, işlevlerle çalışmaz ( ancak gelecekteki yol haritasındadır ).
✔️ Temiz dosyalarımı DI'ye özgü mantıkla karıştırmak istemiyorum — bu, etki alanı ile teknoloji arasında bir ayrım yaparak yapmaya çalıştığımız her şeye aykırı.
Öyleyse, toparlamaya başlarken, bu yaklaşımı kullanmanın faydaları nelerdir?
Yararları yaygın olarak şu şekilde belgelenmiştir:
✔️ Bir hizmet üzerinden etki alanı mantığının sızmasını önler.
✔️ Etki alanı modeli ile girdiler ve çıktılar için kullanılan cihazlar/hizmetler arasındaki net ayrım.
✔️ Teknoloji kilitlenmesini önleyin.
✔️ Varlıkları kapsayan teknik olmayan kullanım durumlarına izin verir.
✔️ Kodun zaman içinde daha kolay değiştirilmesini ve uyarlanmasını sağlar.
✔️ Net ayırma, kodumuzun daha kolay ve daha etkili bir şekilde test edilmesini sağlar.
✔️ Alan modelinin herhangi bir teknik uygulama içermemesine izin verir, yani yalnızca alan adına ve onun iş mantığına odaklanır.
✔️ Tek Sorumluluğa yani SOLID ilkelerine uygundur .
Lütfen gidin ve benzer içerikler için YouTube kanalıma abone olun!
Sizinle aşağıdakilerden herhangi birinde de bağlantı kurmak isterim:
https://www.linkedin.com/in/lee-james-gilmore/
https://twitter.com/LeeJamesGilmore
Gönderileri beğendiyseniz lütfen daha fazla gönderi/dizi için profilimi takip edin Lee James Gilmore ve bağlanmayı ve Merhaba demeyi unutmayın
Beğendiyseniz lütfen gönderinin altındaki 'alkış' özelliğini de kullanın! (Birden fazla alkışlayabilirsiniz!!)
“ Merhaba, ben Lee, Birleşik Krallık'ta yerleşik bir AWS Community Builder, Blogger, AWS sertifikalı bulut mimarı ve Enterprise Serverless Architect; şu anda City Electrical Factors (İngiltere) ve City Electric Supply (ABD) için çalışıyor ve son 6 yıldır AWS'de tam yığın JavaScript'te çalışıyor.
Kendimi AWS'ye, yeniliğe, yazılım mimarisine ve teknolojiye her şeyi seven bir sunucusuz savunucusu olarak görüyorum. ”
*** Sağlanan bilgiler kendi kişisel görüşlerimdir ve bilgilerin kullanımıyla ilgili hiçbir sorumluluk kabul etmiyorum. ***
Aşağıdakiler de ilginizi çekebilir:Sunucusuz İçerik
Java'da volatile anahtar kelimesini kullandığımızda perde arkasında neler olduğuna ve neden senkronizasyonun yerini tam olarak almadığına kısa bir bakış uçucu anahtar kelime genelinde. Bu anahtar kelime, bir değişkende yapılan herhangi bir değişikliğin diğer ileti dizileri tarafından hemen görülebilmesini sağlamak için kullanılabilir, bu nedenle verilerimizin eski, senkronize olmayan ve yanlış hale gelmesini önlemeye yardımcı olur.
Ağustos 2018'de merkezi Boston, Massachusetts, ABD'de bulunan bir startup şirketi olan Aspitio (Pvt) Ltd'de stajyer olarak çalışmaya başladım. birincil amacı, BT danışmanlığı, yazılım geliştirme ve bakımı ve bağımsız yazılım testi dahil olmak üzere okullara BT hizmetleri sunmaktır.
Tarih kitapları bana iki dünya savaşı öğretti: I ve II. Akademisyenler, politikacılar, yorumcular, medya kuruluşları bir sonraki Dünya Savaşı hakkında uzun süredir spekülasyonlar yapıyor ve tahminlerde bulunuyor: Kontrolden çıkan bölgesel bir çatışma, hakimiyet için dünya güçlerinin çatışması, geleneksel savaşa dönüşen felç edici bir siber savaş.
Nihayet! 2022 En İyi Yeni Müziklerime hoş geldiniz. Bunu her yıl arkadaşlarla bağlantı kurmak için paylaşıyorum.
COVID-19 salgınının Grand Rapids şehri ve sakinleri üzerinde derin bir etkisi oldu. Virüs 2020'nin başlarında ilk ortaya çıktığında, topluluktaki birçok kişi başlangıçta ciddiyetine ve yayılmasını kontrol etmek için katı önlemlere duyulan ihtiyaç konusunda şüpheciydi.
Proje Arka Planı Bir iş teklifi ve kendi alanımda, zamanımda ve tarzımda yeni bir hayata başlama hayaliyle 2019 yılında yeni bir şehre taşındım. Kötü PG durumu göz önüne alındığında, arkadaşım ve ben bir daire kiralamaya karar verdik.