Durum Diyagramı Örneği: Bir Abonelik Yaşam Döngüsünü Durum Makinesi Olarak Modellemek

Bir SaaS aboneliği için çözümlü UML durum makinesi diyagramı: durumlar, olaylar, koşullar, seçim noktaları, bileşik durum ve durum diyagramının erken yakaladığı hatalar.

· Kurucu ve geliştirici

Yayımlandı:

Durum Diyagramı Örneği: Bir Abonelik Yaşam Döngüsünü Durum Makinesi Olarak Modellemek

Abonelik hataları durum hatalarıdır. Bir müşteri iptal ettikten sonra erişimini korur. Ödemesi gecikmiş bir hesap ödeme yapar ama kilitli kalır. Kartı olmayan birinin denemesi biter ve bundan sonra ne olacağını söyleyen bir kural yoktur. Bunların her biri, kimsenin çizmediği bir geçiştir.

Genellikle durum diyagramı denilen durum makinesi diyagramı, tek bir nesnenin içinde bulunabileceği her durumu ve onu başka bir duruma taşıyan her olayı listeler. Eksik geçişler destek taleplerinde değil, incelemede ortaya çıkar. Bu yazı bir SaaS aboneliği için bir durum diyagramı kuruyor; modeli gerçek bir sistemle karşılaştırabilmeniz için Stripe Billing'in belgelediği durumları kullanıyor ve notasyonu yeri geldikçe açıklıyor.

Ne zaman durum makinesi çizilir

Tek bir nesnenin kuralları olan bir yaşam döngüsü varsa bir tane çizin: bir sipariş, bir abonelik, bir ödeme, bir destek talebi, bir dağıtım. Uyarı işaretleri tanıdıktır:

  • Üçten fazla değeri olan ve kodda birçok yerde kontrol edilen bir status sütunu.
  • Birbiriyle çelişebilen is_canceled ve is_paused gibi boolean bayraklar.
  • Belirli bir durumdan bir şeyin "olup olamayacağı" üzerine tartışmalar.

Birkaç katılımcı arasındaki bir konuşma için durum diyagramı yanlış resimdir; orada bir sekans diyagramı mesajların sırasını gösterir. Çok sayıda kişi ve devir teslim içeren bir iş süreci için de yanlış resimdir; oraya bir BPMN diyagramı daha iyi uyar.

Notasyon

Öğe Notasyon Anlamı
Durum Köşeleri yuvarlatılmış dikdörtgen Nesnenin bir olay gelene kadar kaldığı koşul
Başlangıç sözde durumu Küçük dolu daire Makinenin başladığı yer
Son durum Bir halkanın içinde dolu daire Makine bitmiştir
Geçiş event [guard] / action etiketli ok Olay gerçekleştiğinde ve koşul doğruysa geçilir
Seçim Eşkenar dörtgen Çıkan oklardaki koşullar hedefi belirler
Bileşik durum Durumları içeren bir durum İçindeki her şeyin paylaştığı kurallar
İç davranış entry /, exit /, do / Girerken, çıkarken ya da durumdayken çalışır

Bir geçiş etiketinin her parçası isteğe bağlıdır. invoice paid tek başına bir olaydır, [setting: unpaid] tek başına bir koşuldur ve cancel / revoke access bir eylemi olan bir olaydır. Sözdizimi ve semboller UML 2.5.1 spesifikasyonundan gelir.

Abonelik durumları

Örnek, otomatik kart ödemeleriyle Stripe'ın abonelik genel bakışındaki durumları kullanır:

Durum Anlamı Erişim
incomplete İlk ödeme henüz yapılmadı; müşterinin 23 saati var Yok
incomplete_expired İlk ödeme hiç başarılı olmadı; hiçbir şey faturalanmaz Yok
trialing Deneme süresinde Var
active Sorunsuz durumda Var
past_due Son faturanın ödemesi başarısız oldu ya da denenmedi Sizin seçiminiz
unpaid Yeniden denemeler tükendi ve ayarlarınız bu sonucu seçti Yok
paused Deneme ödeme yöntemi olmadan bitti ve duraklatma seçildi Yok
canceled Sona erdi; Stripe bunu son durum olarak tanımlar Yok

Birçok ürün, ödeme yeniden denemeleri sürerken past_due sırasında erişimi korur; bu örnek de öyle yapıyor. Bu kararı diyagrama yazın; insanların unuttuğu karar budur.

Geçişleri kurmak

Her durumu alın ve orada hangi olayların gerçekleşebileceğini sorun.

  1. Başlangıç. subscribe [trial] trialing'e; subscribe [no trial] incomplete'e götürür.
  2. İlk ödeme. incomplete'ten invoice paid active'e götürür. Ödeme olmadan 23 saat geçerse abonelik incomplete_expired'a geçer ve Stripe faturayı geçersiz kılar. Bu durum son durumdur: yeniden denemek için müşteri yeni bir abonelik başlatır.
  3. Deneme bitişi. trial ends bir seçime gider. [payment succeeds] active'e; bu örnekte [no payment method] paused'a götürür. Stripe bu durumda ne olacağını seçmenize izin verir: bir fatura oluşturmak (varsayılan), iptal etmek ya da duraklatmak. Üçünü birden değil, gerçekten kullandığınız ayarı çizin.
  4. Yenilemeler. active'ten renewal payment fails past_due'ya götürür; invoice paid geri getirir.
  5. Tükenen denemeler. Bir seçim daha: ayarlarınıza bağlı olarak abonelik unpaid ya da canceled'a geçer veya past_due'da kalır. unpaid'den faturanın ödenmesi aboneliği active'e döndürür.
  6. Çıkış. cancel, active'i canceled'a taşır. Dönem sonunda iptal ayrı bir durum değildir: abonelik dönem bitene kadar bir bayrakla active kalır, sonra canceled'a geçer.

Erişim için bileşik bir durum

Burada üç durum erişim verir: trialing, active ve past_due. Onları tek bir bileşik durumun, Access granted'ın içine çizmek kuralı bir kez yazmanızı sağlar: entry / grant access ve exit / revoke access. Bileşik durumdan çıkan her geçiş, hangi durumdan başlarsa başlasın erişimi kaldırır; böylece hiçbir yol bunu unutamaz. Bileşik durumun içindeki durumlar arasında geçmek, örneğin trialing'den active'e, onu terk etmez ve bu eylemleri çalıştırmaz.

Başlangıç noktası trialing ya da incomplete'e gider. Trialing, active ve past due bir Access granted çerçevesindedir. Deneme bitişi bir seçimle active ya da paused'a gider. Başarısız yenileme active'i past due'ya taşır; tükenen denemeler unpaid ya da canceled'a, sonra son duruma gider.

15 bileşen · 17 bağlantı

Archboard'da aç
Diyagram içeriği
  • Access granted
  • trialing
  • active
  • past_due
  • paused
  • incomplete
  • incomplete_expired
  • unpaid
  • canceled
  • subscribe [trial]
  • subscribe [no trial]
  • invoice paid
  • after 23 h / void invoice
  • trial ends
  • [payment succeeds]
  • [no payment method]
  • resume [payment succeeds]
  • renewal payment fails
  • retries exhausted
  • [setting: unpaid]
  • [setting: cancel]
  • cancel
Stripe Billing'in belgelediği durumları kullanan bir SaaS aboneliği durum makinesi: deneme ve ilk ödeme, erişim veren her durum için bileşik bir durum, başarısız yenilemeler ve bir aboneliğin bitebileceği iki yol.

Nasıl okunur:

  • Üst. Başlangıç noktası denemeye göre ayrılır: bileşik durumun içindeki trialing ya da dışındaki incomplete. incomplete'ten ödeme active'e, ödemesiz geçen 23 saat ise incomplete_expired'a ve sağdaki son duruma götürür.
  • Orta, Access granted. trial ends bir seçime ulaşır: ödeme başarılı olursa active, ödeme yöntemi yoksa soldaki paused. Başarısız bir yenileme active'i past_due'ya taşır, ödeme de geri taşır.
  • Alt. Yeniden denemeler tükendiğinde ikinci bir seçim aboneliği unpaid ya da canceled'a gönderir. unpaid hâlâ ödeme yaparak active'e dönebilir; canceled son durumda biter.
  • Çerçeveye giren kenarlar erişim verir, çerçeveden çıkan kenarlar erişimi kaldırır.

Diyagramdan koda

Diyagram bir geçiş tablosuna karşılık gelir. Tabloda olmayan her şey reddedilir:

type Status = 'incomplete' | 'incomplete_expired' | 'trialing' | 'active'
  | 'past_due' | 'unpaid' | 'paused' | 'canceled';

const transitions: Record<Status, Partial<Record<string, Status>>> = {
  incomplete: { invoice_paid: 'active', expired: 'incomplete_expired' },
  trialing: { trial_ended_paid: 'active', trial_ended_no_method: 'paused' },
  active: { payment_failed: 'past_due', cancel: 'canceled' },
  past_due: { invoice_paid: 'active', retries_exhausted: 'unpaid' },
  unpaid: { invoice_paid: 'active' },
  paused: { resumed: 'active' },
  incomplete_expired: {},
  canceled: {},
};

function next(status: Status, event: string): Status {
  const target = transitions[status][event];
  if (!target) throw new Error(`${event} is not allowed in ${status}`);
  return target;
}

Olaylar bir ödeme sağlayıcısının webhook'larından geliyorsa sıraya güvenmeyin. Stripe'ın webhook belgeleri, olayların oluşturuldukları sırayla ulaşacağını garanti etmediğini söyler. Her olayı aboneliğin güncel durumunu çekmek için bir neden olarak görün, sonra geçişi o duruma uygulayın.

Yaygın hatalar

  • Eksik olaylar. Her durum için her olayı kontrol edin. "Müşteri past_due iken iptal ederse ne olur?" diyagramın yanıtlaması gereken bir sorudur.
  • Durum olarak çizilmiş bayraklar. Dönem sonunda iptal, bir indirim ya da bir koltuk sayısı bir durumun özellikleridir, durum değildir.
  • Durum olarak çizilmiş eylemler. "Ödeme hatırlatma e-postası gönder" bir geçişteki eylem ya da bir entry davranışıdır, aboneliğin beklediği bir yer değildir.
  • Son durumun olmaması. Yaşam döngüsünün nerede bittiğini gösterin ki kimse iptal edilmiş bir aboneliği canlandıran kod yazmasın.
  • Çakışan ya da boşluk bırakan koşullar. Bir seçimden çıkan koşullar her durumu tam olarak bir kez kapsamalıdır; gerekirse [else] ekleyin.
  • Bir diyagramda iki yaşam döngüsü. Aboneliğin ve faturalarının ayrı durum makineleri vardır. Onları birleştirmek yerine olaylarla bağlayın.

Diyagramı onu uygulayan kodun yanında tutun ve ikisini aynı pull request'te inceleyin; eskimeyen mimari diyagramlar yazısında anlatıldığı gibi.

Archboard'da oluşturun

  1. Google ya da GitHub ile giriş yapın ve bir diyagram oluşturun.
  2. UML paketinden her abonelik durumu için bir Durum ekleyin.
  3. trialing, active ve past_due'nun etrafına Access granted adlı bir Temel paketi Çerçeve ekleyin.
  4. Başlangıç durumu için Temel paketinden küçük, dolgulu bir Elips, her seçim için bir Eşkenar dörtgen ve her son durum için noktalı daire biçiminde bir İkon ekleyin.
  5. Durumları event [guard] / action etiketli kenarlarla bağlayın.
  6. Bileşik durumun giriş ve çıkış eylemleri için bir UML Not ekleyin.

Örnek 14 diyagram düğümü kullanıyor ve Free planın sınırları içinde kalıyor. MCP üzerinden bağlanan bir yapay zekâ ajanıyla durum enum'ınızı yapıştırıp durumları ona taslak olarak çizdirebilir, sonra her geçişi kendiniz kontrol edebilirsiniz.

SSS

Durum diyagramı ile akış şeması arasındaki fark nedir? Akış şeması bir sürecin adımlarını sırayla gösterir. Durum diyagramı ise bir nesnenin içinde bulunabileceği koşulları ve onu bunlar arasında hangi olayların taşıdığını gösterir; yani sıradaki adımı değil, neye izin verildiğini yanıtlar.

Status sütunumun her değeri bir durum olmalı mı? Davranışı değiştiren her değer olmalı. İki değer her durumda aynı davranıyorsa onları birleştirin; tek bir değer iki davranışı gizliyorsa ikiye bölün.

Webhook'lar bir durum makinesinde nereye oturur? Onlar olaydır. Onları doğrulayın, sağlayıcıdan güncel durumu çekin ve geçişi uygulayın; çünkü olaylar sıra dışı ya da birden fazla kez gelebilir.

Bileşik bir duruma ihtiyacım var mı? Birkaç durum erişim ya da faturalama gibi bir kuralı paylaşıyorsa bir tane kullanın. Birçok okta tekrarlayacağınız bir kuralı tek bir giriş ve tek bir çıkış eylemine dönüştürür.

Geçiş etiketleri ne kadar ayrıntılı olmalı? Olayı alan terimleriyle adlandırın ve yalnızca aynı olayla iki ok çıktığında bir koşul ekleyin. Erişim vermek gibi doğruluk açısından önemli eylemleri diyagrama koyun.

Ücretsiz başlayın — tek kullanıcı, kredi kartı gerekmez.

İlgili yazılar

← Blog'a dön

Bir dakikada canvas açın

Google veya GitHub ile giriş yapın. Tek koltuk ücretsiz; ekip katılınca planı yükseltin.