{"id":364721,"date":"2024-05-21T02:22:52","date_gmt":"2024-05-21T02:22:52","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=364721"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=364721","title":{"rendered":"<span>\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e!<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b \u0434\u0440\u0443\u0433\u0430 \u0441 \u043f\u043e\u043d\u044f\u0442\u0438\u0435\u043c &#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;. \u0421 \u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043e\u043d \u0447\u0430\u0441\u0442\u043e \u0430\u0442\u0430\u043a\u043e\u0432\u0430\u043b \u043c\u0435\u043d\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 &#171;\u0410 \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c? \u0410 \u043a\u0430\u043a \u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c?&#187;. \u0412 \u043e\u0434\u0438\u043d \u043c\u043e\u043c\u0435\u043d\u0442 \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0438\u043d\u0443\u0442\u044c \u0435\u043c\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u0441 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u043c, \u043d\u043e \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0435\u0440\u0435\u0447\u0438\u0442\u0430\u0432 \u043a\u043d\u0438\u0433\u0443 \u0420\u043e\u0431\u0435\u0440\u0442\u0430 \u041c\u0430\u0440\u0442\u0438\u043d\u0430 <a href=\"https:\/\/www.chitai-gorod.ru\/product\/chistaya-arhitektura-iskusstvo-razrabotki-programmnogo-obespecheniya-2640391\" rel=\"noopener noreferrer nofollow\">&#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;<\/a>, \u043e\u0441\u0432\u0435\u0436\u0438\u0432 \u0441\u0432\u043e\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0432\u0448\u0438\u0441\u044c \u0432 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0438, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u044e.<\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0447\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u0427\u0438\u0441\u0442\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0430\u0437\u043e\u0439 &#8212; <code>\u0441\u0442\u0440\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u043e\u043a\u0440\u0443\u0433 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438<\/code>:<\/p>\n<ul>\n<li>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432\u0441\u044f\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438, \u0411\u0414, HTTP \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0442.\u0434.;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c \u043e\u0442\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0430\u0441\u0442\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u044d\u0442\u043e\u0433\u043e:<\/p>\n<ol>\n<li>\n<p>\u041d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432\/\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u041c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043d\u0438 \u043e \u043a\u0430\u043a\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 &#8212; \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0447\u0435\u0433\u043e-\u043b\u0438\u0431\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e &#8212; \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438\/\u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Domain first \u043f\u043e\u0434\u0445\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0435\u0441\u0442\u044c 3 \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>Code first<\/p>\n<\/li>\n<li>\n<p>Database first<\/p>\n<\/li>\n<li>\n<p>Model first<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f API \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>Code first<\/p>\n<\/li>\n<li>\n<p>Contract first<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u044f \u0431\u044b \u0434\u0430\u043b \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>Domain-first<\/code><\/p>\n<\/div>\n<\/details>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u044d\u0442\u0443 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 &#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a99\/9f8\/dd4\/a999f8dd401afd04bcfef3687e785d2a.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a99\/9f8\/dd4\/a999f8dd401afd04bcfef3687e785d2a.png\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0447\u0442\u043e \u043d\u0430 \u043d\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u0421\u043b\u0435\u0432\u0430 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043e\u0431\u0449\u0438\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041c\u043e\u0434\u0443\u043b\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u043e \u0441\u043b\u043e\u044f\u043c (\u0441\u043d\u0438\u0437\u0443 \u0432\u0432\u0435\u0440\u0445):<\/p>\n<ol>\n<li>\n<p>Entities <\/p>\n<ul>\n<li>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0441\u0430\u043c\u0443\u044e \u0432\u0430\u0436\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443\/\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0440\u0430\u0441\u0447\u0435\u0442 \u0443\u0433\u043b\u0430 \u0431\u0440\u043e\u0441\u043a\u0430 \u0441\u043d\u0430\u0440\u044f\u0434\u0430<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Use Cases <\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0448\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b<\/p>\n<\/li>\n<li>\n<p>\u042d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 &#8212; \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u0443\u0435\u0442 Entities<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0443\u0433\u043b\u0430 \u0443\u0434\u0430\u0440\u0430 \u0432 \u0431\u0438\u043b\u044c\u044f\u0440\u0434\u0435 \u0438 \u0442\u0440\u0430\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0430 \u0438\u0437 \u043f\u0443\u0448\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b\/\u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u044b <\/p>\n<ul>\n<li>\n<p>\u0422\u0435, \u0441 \u043a\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: MVC \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430 \u0434\u043b\u044f gRPC, \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f (MVVM)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>UI, \u0411\u0414, \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 <\/p>\n<ul>\n<li>\n<p>\u042d\u0442\u043e \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043a\u043d\u0438\u0433\u0435 \u0420\u043e\u0431\u0435\u0440\u0442 \u0424\u0430\u0443\u043b\u0435\u0440 \u0434\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>Critical Business Rules &#8212; \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u0437\u0430\u043a\u043e\u043d\u044b, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438 \u0431\u0435\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c<\/p>\n<blockquote>\n<p>&#8230; they are critical to the business itself, and would exist even if there were no system to automate them<\/p>\n<\/blockquote>\n<\/li>\n<li>\n<p>Critical Business Data &#8212; \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044d\u0442\u0438\u0445 \u0441\u0430\u043c\u044b\u0445 Critical Business Rules<\/p>\n<blockquote>\n<p>&#8230; the data that would exist even if the system were not automated<\/p>\n<\/blockquote>\n<\/li>\n<\/ul>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u0441\u0430\u043c\u043e\u0433\u043e <code>Entity<\/code>:<\/p>\n<blockquote>\n<p>Entity &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 Critical Business Rules \u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u044b Critical Business Data<\/p>\n<\/blockquote>\n<p>\u0410 <code>Use Cases<\/code> &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u0443\u044e\u0442 \u044d\u0442\u0438\u043c\u0438 <code>Entity<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b:<\/p>\n<ul>\n<li>\n<p>Critical Business Rules &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u043e\u0439 \u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u043e \u043a\u0440\u0435\u0434\u0438\u0442\u0443;<\/p>\n<\/li>\n<li>\n<p>Critical Business Data &#8212; \u044d\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430: \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0430\u044f \u0441\u0442\u0430\u0432\u043a\u0430, \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u043b\u043e\u0433\u0430, \u0432\u0440\u0435\u043c\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0432\u0430\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>Entity &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 <code>Critical Business Rules<\/code> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u0443\u044e \u0441\u0442\u0430\u0432\u043a\u0443 \u043f\u043e <code>Critical Business Data<\/code>;<\/p>\n<\/li>\n<li>\n<p>Use Case &#8212; \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0432\u0437\u044f\u0442\u044c \u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0438\u043b\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0432\u0437\u043d\u043e\u0441\u0443.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c 2 \u0432\u0435\u0449\u0438:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <strong>\u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/strong> &#8212; \u043d\u0435 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u0442\u043e, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438);<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0434\u0443\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u043b\u043e\u0435\u0432 \u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c &#8212; \u043e\u0434\u0438\u043d \u043c\u043e\u0434\u0443\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0441\u0441\u044b\u043b\u0430\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e \u044d\u0442\u043e\u0439 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043e\u043d \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u043f\u0440\u0430\u0432\u0430 \u0438\u0434\u0435\u0442 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 &#8212; \u0442\u043e, \u043a\u0430\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0435\u0431\u044f \u0432\u0435\u0441\u0442\u0438 \u0432 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 UML \u0438 \u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0427\u0442\u043e \u043d\u0430 \u043d\u0435\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>Controller<\/code> &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 3 \u0443\u0440\u043e\u0432\u043d\u044f, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u0431\u0449\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Input Port<\/code> &#8212; \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0430\u0448\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Interactor<\/code> &#8212; \u044d\u0442\u043e \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>Use Case Input Port<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Output Port<\/code> &#8212; \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0438\u0441\u044c\u043c\u0430 \u0438 \u0442.\u0434.;<\/p>\n<\/li>\n<li>\n<p><code>Presenter<\/code> &#8212; \u044d\u0442\u043e \u0441\u0430\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>Use Case Output Port<\/code>. \u0418\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c Presenter, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043d\u043e\u0432\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 SQL \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u043a\u0432\u043e\u0437\u044c \u0432\u0441\u044e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443, \u043e\u0442 <code>Controller<\/code> \u043a <code>Presenter<\/code>, \u043a\u0430\u0441\u0430\u044f\u0441\u044c <code>Use Case Interactor<\/code>, \u0434\u0432\u0438\u0436\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0435\u043b\u043a\u0430. \u042d\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f &#8212; \u043a\u0442\u043e-\u043a\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a: <code>Controller<\/code> -> <code>Use Case Interactor<\/code> -> <code>Presenter<\/code>.<br \/> \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0441\u0434\u0435\u043b\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432\u044b\u0437\u0432\u0430\u043b \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043c\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u044b\u0437\u0432\u0430\u043b \u043c\u0435\u0442\u043e\u0434 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0442\u043e, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u043a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u043d\u0435\u0442 \u044f\u0441\u043d\u0435\u0435.<\/p>\n<h2>\u0420\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443<\/h2>\n<h3>\u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0438\u0434\u0435\u044e \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f: \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0431\u0438\u043b\u0435\u0442\u043e\u0432 \u0432 \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0435. \u0412\u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u0439\u043c\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u0438\u0440\u0430.<\/p>\n<p><em>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u0430 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439. 3.. 2.. 1.. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u044b<\/em><br \/> <em>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438. 3.. 2.. 1.. \u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0430<\/em><\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0444\u0438\u043b\u044c\u043c\u043e\u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u0441\u0435\u0430\u043d\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u0435\u0430\u043d\u0441 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0435\u0441\u0442;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0434\u043d\u043e \u043c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043a\u0443\u043f\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0447\u0435\u043b\u043e\u0432\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u0441\u0435\u0430\u043d\u0441\u0430 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043a\u0443\u043f\u0438\u0442\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043b\u0438\u0431\u043e \u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 \u043d\u0438\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b \u043d\u0435\u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0438\u0442.<\/p>\n<blockquote>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043a\u0440\u043e\u043c\u0435 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u043c\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c: \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0441\u0435\u0430\u043d\u0441\u044b, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u0438 \u0442.\u0434.<\/p>\n<\/blockquote>\n<h3>\u041c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435, \u0441 \u0447\u0435\u043c \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u041d\u0430\u0448\u0430 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u043a\u0443\u043f\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0430\u0445. \u041f\u043e \u0438\u0434\u0435\u0435, \u0441\u0435\u0430\u043d\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043f\u043e\u043a\u0430\u0437\u0430 \u0444\u0438\u043b\u044c\u043c\u0430, \u0441\u0430\u043c \u0444\u0438\u043b\u044c\u043c, \u0437\u0430\u043b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. (!) \u041d\u043e \u043d\u0430\u0448\u0430 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c &#8212; \u044d\u0442\u043e \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0441\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0441 \u0441\u0435\u0430\u043d\u0441 &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0441\u0442 \u0441 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0430\u043d\u0441 \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">class Session {     \/\/\/ &lt;summary>     \/\/\/ \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0435\u0430\u043d\u0441\u0430     \/\/\/ &lt;\/summary>     public int Id { get; }         private readonly Seat[] _seats;          \/\/\/ &lt;summary>     \/\/\/ \u041c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0430\u043d\u0441\u0430      \/\/\/ &lt;\/summary>     public IReadOnlyCollection&lt;Seat> Seats => _seats;          public Session(SessionInterval interval, int movieId, IEnumerable&lt;Seat> seats)     {         ArgumentNullException.ThrowIfNull(interval);         ArgumentNullException.ThrowIfNull(seats);                  Interval = interval;         MovieId = movieId;         _seats = BuildSeatsArray(seats);     }      private static Seat[] BuildSeatsArray(IEnumerable&lt;Seat> seats)     {         var array = seats.ToArray();         for (var i = 0; i &lt; array.Length; i++)         {             if (array[i] == null!)             {                 throw new ArgumentNullException(nameof(seats), $\"\u041e\u0431\u044a\u0435\u043a\u0442 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 {i} \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0431\u044b\u043b null\");             }         }          return array;     }          \/\/ ... } <\/code><\/pre>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0440\u0443\u0448\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u2014 \u0441\u0430\u043c\u0438\u043c \u043d\u0430\u043a\u043e\u0441\u044f\u0447\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430, \u0433\u0434\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u2014 \u0432\u0441\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u043d\u0430\u0440\u0443\u0436\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 (get-only, IReadOnlyCollection);<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043c\u0435\u0441\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>Seat<\/code>, \u043d\u043e \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0435\u0449\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e, \u2014 \u044d\u0442\u043e \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>\u041c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c 3 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f: \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e, \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u043e. \u041f\u0440\u0438\u0447\u0435\u043c, \u0435\u0441\u043b\u0438 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438\u043b\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0442\u043e \u0417\u0410 \u041a\u0415\u041c-\u0422\u041e. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0443\u043c\u0430\u043b\u0438 \u043f\u0440\u043e \u0411\u0414, \u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">enum SeatType {     Free = 0,     Booked = 1,     Bought = 2, }  class Seat {     public SeatType Type { get; set; }     public int SessionId { get; set; }     public Session Session { get; set; }     public int Number { get; set; }     public int? ClientId { get; set; } } <\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 POCO \u043a\u043b\u0430\u0441\u0441, \u0433\u0434\u0435 \u0432\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0430 \u043d\u0430\u0440\u0443\u0436\u0443.<\/p>\n<p>\u041c\u044b, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0438 \u043b\u043e\u0433\u0438\u043a\u0438.<br \/> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f <code>Id<\/code> \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e:<\/p>\n<pre><code class=\"cs\">class Seat {     public bool TryGetClientIdBooked(out int clientId)     {         if (Type == SeatType.Booked)         {             clientId = ClientId.Value;             return true;         }         clientId = default;         return true;     } } <\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043b\u043e\u0445 \u0442\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u0438 \u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u043e\u0431\u0440\u043e\u0441\u043e\u0432\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442: \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 <code>null<\/code> \u0434\u043b\u044f \u043a\u0443\u043f\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0423 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0435 <code>ClientId<\/code> \u0443 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u0449\u0438: \u0442\u043e\u0442 \u043a\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0438 \u043a\u0442\u043e \u043a\u0443\u043f\u0438\u043b \u043c\u0435\u0441\u0442\u043e &#8212; \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u044d\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0438 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 2 \u043f\u0443\u043d\u043a\u0442\u0430. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c &#8212; \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430. \u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">abstract class Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041d\u043e\u043c\u0435\u0440 \u043c\u0435\u0441\u0442\u0430 \u0432 \u0437\u0430\u043b\u0435     \/\/\/ &lt;\/summary>     public int Number { get; }     protected internal Seat(int number)     {         if (number &lt; 1)         {             throw new ArgumentOutOfRangeException(nameof(number), number, \"\u041d\u043e\u043c\u0435\u0440 \u043c\u0435\u0441\u0442\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\");         }         Number = number;     } }   class FreeSeat: Seat {     public FreeSeat(int number) : base(number)     { } }  class BookedSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int ClientId { get; }      public BookedSeat(int number, int clientId) : base(number)     {         ClientId = clientId;     } }  class BoughtSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0443\u043f\u0438\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int ClientId { get; }      public BoughtSeat(int number, int clientId) : base(number)     {         ClientId = clientId;     } } <\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u0435\u0441\u0442\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u0442;<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0442\u0438\u043f\u044b \u043c\u0435\u0441\u0442 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u044b &#8212; \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043f\u043e\u043c\u0435\u0447\u0435\u043d <code>internal<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0434\u0442\u0438\u043f\u044b \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0431\u043e\u0440\u043a\u0435 \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u043d\u0438\u043a\u0442\u043e \u0441\u0432\u0438\u043d\u044c\u044e \u043d\u0435 \u043f\u043e\u0434\u043b\u043e\u0436\u0438\u0442;<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u043d\u043e\u043c\u0435\u0440\u0430 \u043c\u0435\u0441\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u043c\u0443;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0441\u0445\u0435\u043c\u044b \u0411\u0414 (<code>Session<\/code> \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0441\u0442\u0430 \u0441 \u0441\u0435\u0430\u043d\u0441\u043e\u043c).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0443\u043d\u043a\u0442 1 \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043b\u0441\u044f \u043d\u0430 \u0445\u043e\u0434\u0443: \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441\u0442\u0430\u043b\u0438 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0441\u043b\u043e\u043c\u0430\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f.<\/p>\n<p>\u041f\u0443\u043d\u043a\u0442 3 &#8212; \u043d\u0430 \u043b\u044e\u0431\u0438\u0442\u0435\u043b\u044f. \u0421\u0435\u0439\u0447\u0430\u0441 \u0438\u0437 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043f\u043e\u043b\u0435 <code>ClientId<\/code>, \u043d\u043e \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442\u0441\u044f, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c \u043f\u043e-\u043e\u0441\u043e\u0431\u043e\u043c\u0443 (\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044d\u0442\u043e \u043d\u0435 \u0437\u0430\u0442\u0440\u043e\u043d\u0435\u0442):<\/p>\n<pre><code class=\"cs\">public class BoughtSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0443\u043f\u0438\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int BoughtId { get; }      public BoughtSeat(int number, int boughtId) : base(number)     {         BoughtId = boughtId;     } }  public class BookedSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int BookedId { get; }      public BookedSeat(int number, int bookedId) : base(number)     {         BookedId = bookedId;     } } <\/code><\/pre>\n<p>\u041c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u0438\u0431\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u043b\u0438\u0431\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e, \u043f\u0440\u0438\u0447\u0435\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u0432\u043e\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430. \u041e\u0431\u044f\u0437\u0443\u0435\u043c \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438. \u0412 C# \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/p>\n<pre><code class=\"cs\">abstract class Seat {     \/\/\/ &lt;summary>     \/\/\/ \u0417\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0437\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c     \/\/\/ &lt;\/summary>     \/\/\/ &lt;param name=\"clientId\">Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e&lt;\/param>     \/\/\/ &lt;returns>\u0417\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e&lt;\/returns>     \/\/\/ &lt;exception cref=\"SeatBoughtException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0436\u0435 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBookedException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0436\u0435 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     public abstract BookedSeat Book(int clientId);          \/\/\/ &lt;summary>     \/\/\/ \u041a\u0443\u043f\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044f     \/\/\/ &lt;\/summary>     \/\/\/ &lt;param name=\"clientId\">Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043a\u0443\u043f\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e&lt;\/param>     \/\/\/ &lt;returns>\u041a\u0443\u043f\u043b\u0435\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e&lt;\/returns>     \/\/\/ &lt;exception cref=\"SeatBoughtException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0436\u0435 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBookedException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     public abstract BoughtSeat Buy(int clientId); }  class BookedSeat: Seat {     public override BookedSeat Book(int clientId)     {         if (ClientId == clientId)         {             return this;         }                  throw new SeatBookedException(ClientId);     }      public override BoughtSeat Buy(int clientId)     {         if (ClientId == clientId)         {             return new BoughtSeat(Number, clientId);         }          throw new SeatBookedException(ClientId);     } } <\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0435. \u042d\u0442\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0443\u0436\u0435 \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u0432 \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0435\u0430\u043d\u0441\u0430.<\/p>\n<pre><code class=\"cs\">class Session {     \/\/ \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e FindSeatByPlace \u043e\u043f\u0443\u0441\u0442\u0438\u043b - \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f          \/\/\/ &lt;summary>     \/\/\/ \u041a\u0443\u043f\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430     \/\/\/ &lt;\/summary>     \/\/\/ &lt;param name=\"place\">\u041c\u0435\u0441\u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0443\u0436\u043d\u043e \u043a\u0443\u043f\u0438\u0442\u044c&lt;\/param>     \/\/\/ &lt;param name=\"clientId\">\u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043a\u0443\u043f\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e&lt;\/param>     \/\/\/ &lt;returns>&lt;c>true&lt;\/c> - \u043c\u0435\u0441\u0442\u043e \u0431\u044b\u043b\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e, &lt;c>false&lt;\/c> - \u043c\u0435\u0441\u0442\u043e \u0423\u0416\u0415 \u0431\u044b\u043b\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e \u044d\u0442\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&lt;\/returns>     \/\/\/ &lt;exception cref=\"SeatNotFoundException\">\u041c\u0435\u0441\u0442\u043e \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBoughtException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0441\u0430\u043c\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBookedException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&lt;\/exception>     public BoughtSeat Buy(int place, int clientId)     {         var (seat, index) = FindSeatByPlace(place);          var bought = seat.Buy(clientId);         if (bought == seat)         {             \/\/ \u041c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e \u044d\u0442\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c             throw new SeatBoughtException(clientId);         }          _seats[index] = seat;         return bought;     }          \/\/\/ &lt;summary>     \/\/\/ \u0417\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0437\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c      \/\/\/ &lt;\/summary>     \/\/\/ &lt;param name=\"place\">\u041c\u0435\u0441\u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c&lt;\/param>     \/\/\/ &lt;param name=\"clientId\">\u041a\u043b\u0438\u0435\u043d\u0442, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e&lt;\/param>     \/\/\/ &lt;returns>&lt;c>true&lt;\/c> - \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e, &lt;c>false&lt;\/c> - \u043c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u044d\u0442\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c&lt;\/returns>     \/\/\/ &lt;exception cref=\"SeatNotFoundException\">\u041c\u0435\u0441\u0442\u043e \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBoughtException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0436\u0435 \u0441\u0430\u043c\u044b\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     \/\/\/ &lt;exception cref=\"SeatBookedException\">\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u044d\u0442\u0438\u043c \u0441\u0430\u043c\u044b\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c&lt;\/exception>     public BookedSeat Book(int place, int clientId)     {         var (seat, index) = FindSeatByPlace(place);         var booked = seat.Book(clientId);         if (booked == seat)         {             \/\/ \u041c\u0435\u0441\u0442\u043e \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 \u044d\u0442\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c             throw new SeatBookedException(clientId);         }                  _seats[index] = booked;         return booked;     } } <\/code><\/pre>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u0430\u0432\u0438\u043b \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0438\u0437 \u043a\u043e\u0434\u0430 &#8212; \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0445\u043e\u0447\u0435\u0442 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u0436\u0435 \u043a\u0443\u043f\u043b\u0435\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u0442\u043e \u0431\u0440\u043e\u0441\u0430\u0435\u0442\u0441\u044f <code>SeatBoughtException<\/code>.<\/p>\n<p><code>Entity<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0434\u0435\u043b\u043e \u0437\u0430 \u043c\u0430\u043b\u044b\u043c &#8212; <code>Use Cases<\/code>.<br \/> \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c 2 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 &#8212; \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u043c\u0435\u0441\u0442. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 &#8212; <code>SeatService<\/code>. \u0412 \u043d\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0448\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430.<\/p>\n<pre><code class=\"cs\">class SeatService {     public Task BookSeatAsync(int sessionId, int place, int clientId, CancellationToken token)     {         \/\/ ...     }          public Task BuySeatAsync(int sessionId, int place, int clientId, CancellationToken token)     {         \/\/ ...     } } <\/code><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0440\u0430\u0442\u044c \u044d\u0442\u0438 \u0441\u0435\u0430\u043d\u0441\u044b \u0438 \u043c\u0435\u0441\u0442\u0430? \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441-\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u0430\u043d\u043d\u044b\u0445: <code>ISessionRepository<\/code>.<br \/> \u041e\u0442 \u043d\u0435\u0433\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e 2 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0435\u0430\u043d\u0441 \u0441 \u0435\u0433\u043e \u043c\u0435\u0441\u0442\u0430\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043c\u0435\u0441\u0442\u0435 (\u043f\u043e\u0441\u043b\u0435 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\/\u043f\u043e\u043a\u0443\u043f\u043a\u0438).<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">interface ISessionRepository {     public Task&lt;Session> GetSessionByIdAsync(int sessionId, CancellationToken token = default);     public Task UpdateSeatAsync(int sessionId, Seat seat, CancellationToken token = default); } <\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"cs\">class SeatService {     private readonly ISessionRepository _sessionRepository;      public SeatService(ISessionRepository sessionRepository)     {         _sessionRepository = sessionRepository;     }          public async Task&lt;BookedSeat> BookSeatAsync(int sessionId, int place, int clientId, CancellationToken token = default)     {         var session = await _sessionRepository.GetSessionByIdAsync(sessionId, token);         var bookedSeat = session.Book(place, clientId);         await _sessionRepository.UpdateSeatAsync(sessionId, bookedSeat, token);         return bookedSeat;     }          public async Task&lt;BoughtSeat> BuySeatAsync(int sessionId, int place, int clientId, CancellationToken token = default)     {         var session = await _sessionRepository.GetSessionByIdAsync(sessionId, token);         var boughtSeat = session.Buy(place, clientId);         await _sessionRepository.UpdateSeatAsync(sessionId, boughtSeat, token);         return boughtSeat;     } } <\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043d\u0430\u0448\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u0430. \u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0434\u0443\u043c\u0430\u0442\u044c \u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u043c\u0438\u0440\u0435.<\/p>\n<h3>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c<\/h3>\n<h4>\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/h4>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430. \u0422\u0435\u043f\u0435\u0440\u044c \u0443\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0441 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 1 \u0432\u0435\u0449\u044c &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <code>ISessionRepository<\/code>. \u041f\u043e \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0411\u0414, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0430\u0434\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0411\u0414. \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e ORM (Entity Framework), \u0438 \u0441\u0445\u0435\u043c\u0443 \u043e\u043f\u0438\u0448\u0443 \u0447\u0435\u0440\u0435\u0437 \u043a\u043b\u0430\u0441\u0441\u044b.<\/p>\n<blockquote>\n<p>\u0414\u043b\u044f \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0411\u0414 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u0440\u0435\u0444\u0438\u043a\u0441 <code>Database<\/code><\/p>\n<\/blockquote>\n<pre><code class=\"cs\">public class DatabaseSession {     public int Id { get; set; }     public DateTime Start { get; set; }     public DateTime End { get; set; }     public int MovieId { get; set; }     public ICollection&lt;DatabaseSeat> Seats { get; set; }  }  public class DatabaseSeat {     public int SessionId { get; set; }     public DatabaseSession Session { get; set; }     public int Number { get; set; }     public SeatType Type { get; set; }     public int? ClientId { get; set; } } <\/code><\/pre>\n<blockquote>\n<p>\u041c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0441\u0435\u0430\u043d\u0441\u0430 \u0443 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 (\u043b\u0438\u0448\u043d\u0438\u0435) \u043f\u043e\u043b\u044f. \u041a\u0430\u043a \u0443\u0436\u0435 \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e, \u043c\u044b \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0443 \u043c\u0435\u0441\u0442, \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 (\u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0441\u0435\u0430\u043d\u0441\u044b, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043c\u0435\u0441\u0442\u0430 \u0432 \u0437\u0430\u043b\u0430\u0445 \u0438 \u0442.\u0434.) &#8212; \u0437\u0430 \u0440\u0430\u043c\u043a\u0430\u043c\u0438 \u043d\u0430\u0448\u0438\u0445 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u0435\u0439.<br \/> \u0412\u043e\u0442 \u0442\u0443\u0442 \u0438 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u043b\u044e\u0441 \u0440\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0411\u0414 \u0438 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 &#8212; \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443 \u0436\u0435 \u0441\u0445\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0435\u0439. \u0412\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f &#8212; \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<\/blockquote>\n<p>\u041e\u0441\u0442\u0430\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u043f\u0440\u043e\u0441 &#8212; \u043a\u0430\u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u043c\u0435\u0441\u0442\u0430 \u043d\u0430\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043b\u0438 \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0435\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438. \u041f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0443\u043c &#8212; \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f:<\/p>\n<pre><code class=\"cs\">public void DoSomething(Seat seat) {     switch (seat)     {         case FreeSeat freeSeat:             \/\/ ...         case BookedSeat bookedSeat:             \/\/ ...         case BoughtSeat boughtSeat:             \/\/ ...         default:             throw new ArgumentException(\"\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \u043c\u0435\u0441\u0442\u0430\");     } } <\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0442 \u043f\u0443\u0442\u044c \u043c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0442\u043e\u0434\/\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u0442\u044c\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u043c\u0435\u0441\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0439\u0442\u0438 \u0412\u0421\u0415 \u0442\u043e\u0447\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e <code>switch<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043c\u043e\u0436\u043d\u043e \u0447\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430, \u043d\u043e \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u043e\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c. \u042f \u0432\u044b\u0431\u0440\u0430\u043b \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u043f\u0430\u0442\u0442\u0435\u0440\u043d <a href=\"https:\/\/metanit.com\/sharp\/patterns\/3.11.php\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c<\/a>.<\/p>\n<pre><code class=\"cs\">public interface ISeatVisitor&lt;out T> {     T Visit(FreeSeat freeSeat);     T Visit(BoughtSeat boughtSeat);     T Visit(BookedSeat bookedSeat); }  abstract class Seat {     public abstract T Accept&lt;T>(ISeatVisitor&lt;T> visitor); }  class FreeSeat: Seat {     public override T Accept&lt;T>(ISeatVisitor&lt;T> visitor)     {         return visitor.Visit(this);     } }   class BookedSeat: Seat {     public override T Accept&lt;T>(ISeatVisitor&lt;T> visitor)     {         return visitor.Visit(this);     } }  class BoughtSeat: Seat {        public override T Accept&lt;T>(ISeatVisitor&lt;T> visitor)     {         return visitor.Visit(this);     } } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u044f \u0441\u0447\u0438\u0442\u0430\u044e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c:<\/p>\n<ul>\n<li>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0435 \u043d\u0430\u0440\u0443\u0448\u0430\u0435\u0442\u0441\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0412\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044f \u043d\u0435 \u0434\u0430\u0435\u0442 \u0437\u043d\u0430\u043d\u0438\u0439 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u0443\u0440\u043e\u0432\u043d\u044e \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0441\u0430\u043c\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 <code>ISessionRepository<\/code>.<\/p>\n<pre><code class=\"cs\">public class PostgresSessionRepository: ISessionRepository {     private readonly SessionDbContext _context;      public PostgresSessionRepository(SessionDbContext context)     {         _context = context;     }          public async Task&lt;Session> GetSessionByIdAsync(int sessionId, CancellationToken token = default)     {         var found = await _context.Sessions                                   .AsNoTracking()                                   .Include(s => s.Seats)                                   .Select(x => new                                    {                                        x.Id,                                        x.Seats                                    })                                   .FirstOrDefaultAsync(s => s.Id == sessionId, token);         if (found is null)         {             \/\/ \u0414\u043e\u043c\u0435\u043d\u043d\u043e\u0435 \u0438\u0441\u043a\u043b\u0447\u0435\u043d\u0438\u0435             throw new SessionNotFoundException(sessionId);         }          return new Session(found.Id, found.Seats.Select(seat => seat.ToDomainSeat()));     }          public async Task UpdateSeatAsync(int sessionId, Seat seat, CancellationToken token = default)     {         var databaseSeat = seat.Accept(new DatabaseSeatMapperSeatVisitor(sessionId));         await _context.Seats                       .Where(s => s.SessionId == sessionId &amp;&amp; s.Number == seat.Number)                       .ExecuteUpdateAsync(calls => calls.SetProperty(s => s.ClientId, databaseSeat.ClientId)                                                         .SetProperty(s => s.Type, databaseSeat.Type), token);     } } <\/code><\/pre>\n<blockquote>\n<p><strong>\u0412\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435!<\/strong><br \/> \u041d\u0435 \u0432\u0441\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, <code>ISessionsRepository<\/code> \u043c\u043e\u0436\u0435\u0442 \u043a\u0438\u043d\u0443\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0441\u0435\u0430\u043d\u0441\u0430 &#8212; \u0433\u043e\u0440\u0430\u0437\u0434\u043e \u0432\u044b\u0433\u043e\u0434\u043d\u0435\u0435 \u043f\u0435\u0440\u0435\u043b\u043e\u0436\u0438\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043d\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0430 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u0441\u044e \u0411\u0414 \u0432 \u043f\u0430\u043c\u044f\u0442\u044c \u0438 \u0442\u0430\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u043e\u0438\u0441\u043a.<br \/> \u041a\u0430\u043a \u0442\u0430\u043a\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u044f\u0442\u044c &#8212; \u0442\u043e\u0447\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043c\u043d\u0435 \u043d\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d, \u043f\u0440\u043e\u0441\u0442\u043e \u044f \u0442\u0430\u043a \u0447\u0443\u0432\u0441\u0442\u0432\u0443\u044e. \u041d\u043e \u0435\u0441\u043b\u0438 \u0438 \u043d\u0430\u0445\u043e\u0436\u0443, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0447\u0435\u0442\u043a\u043e \u0432\u0441\u0435\u043c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u043c\u043e\u0436\u0435\u0442 \u043a\u0438\u043d\u0443\u0442\u044c \u0442\u0430\u043a\u043e\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435. \u0412 C# \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0440\u043e\u043a \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.<\/p>\n<\/blockquote>\n<p>\u0412\u043e\u0442 \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0441\u043b\u043e\u0439 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f 2 \u0432\u0435\u0449\u0430\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u043f\u043f\u0438\u043d\u0433 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u0441\u043b\u043e\u044f\u043c\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0422\u0440\u0430\u043d\u0441\u043b\u0438\u0440\u0443\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043d\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e (\u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 &#8212; \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0441\u0435\u0430\u043d\u0441\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e).<\/p>\n<\/li>\n<\/ul>\n<h4>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438<\/h4>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u044f \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0442\u043e, \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439.<br \/> \u0412\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043b\u044e\u0431\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043e \u0441\u043b\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c RESTful API \u043f\u043e HTTP. \u0422\u043e\u0433\u0434\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439.<\/p>\n<pre><code class=\"cs\">[ApiController] [Route(\"sessions\")] public class SessionsController: ControllerBase {     private readonly ISeatService _seatService;      public SessionsController(ISeatService seatService)     {         _seatService = seatService;     }      [HttpPut(\"{sessionId:int}\/places\/{placeId:int}\/book\")]     public async Task&lt;IActionResult> BookSeat(int sessionId, int placeId, [FromQuery][Required] int clientId, CancellationToken token = default)     {         await _seatService.BookSeatAsync(sessionId, placeId, clientId, token);         return Ok();     }          [HttpPut(\"{sessionId:int}\/places\/{placeId:int}\/buy\")]     public async Task&lt;IActionResult> BuySeat(int sessionId, int placeId, [FromQuery][Required] int clientId, CancellationToken token = default)     {         await _seatService.BuySeatAsync(sessionId, placeId, clientId, token);         return Ok();     } } <\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435 &#8212; \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u0442\u043e\u0442 <code>ISeatService<\/code> \u0438 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<p>\u041d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a \u043e\u0441\u0442\u0430\u0432\u0438\u043b \u0432\u043e\u043f\u0440\u043e\u0441 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439. \u041c\u043e\u0436\u043d\u043e \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c <code>try\/catch<\/code> \u0431\u043b\u043e\u043a, \u043d\u043e \u044f \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0441\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 <a href=\"http:\/\/ASP.NET\" rel=\"noopener noreferrer nofollow\">ASP.NET<\/a> Core \u0438 \u0441\u043e\u0437\u0434\u0430\u043c \u0444\u0438\u043b\u044c\u0442\u0440 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"cs\">class DomainExceptionFilterAttribute: ExceptionFilterAttribute {     public override void OnException(ExceptionContext context)     {         if (context.Exception is not DomainException domainException)         {             return;         }              var responseObject = new {message = domainException.Message};         context.Result = domainException switch                          {                              SeatNotFoundException    => new NotFoundObjectResult(responseObject),                              SessionNotFoundException => new NotFoundObjectResult(responseObject),                              _                        => new BadRequestObjectResult(responseObject)                          };              context.ExceptionHandled = true;     } }  [DomainExceptionFilter] public class SessionsController: ControllerBase {     \/\/ ... } <\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0433\u043e\u0442\u043e\u0432\u043e! \u041a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d <a href=\"https:\/\/github.com\/ashenBlade\/habr-posts\/tree\/clean-architecture\/clean-architecture\/project\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<h3>\u041a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0441 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u043e\u0439<\/h3>\n<p>\u0412 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043e\u0431\u0437\u043e\u0440 \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b. \u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c<\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u0421\u043b\u043e\u0439 \u0438\u0437 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0421\u043b\u043e\u0439 \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">UI, Web, Devices<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442, HTTP<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Controllers\/Gateways<\/p>\n<\/td>\n<td>\n<p align=\"left\">MVC \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Use Cases<\/p>\n<\/td>\n<td>\n<p align=\"left\">SeatService<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">Entities<\/p>\n<\/td>\n<td>\n<p align=\"left\">Seat<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e <code>Entities<\/code> \u0438 <code>Use Cases<\/code> \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u044b \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 (\u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 .NET), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044d\u0442\u0438 2 \u0441\u043b\u043e\u044f \u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d\u0438 \u043e\u043b\u0438\u0446\u0435\u0442\u0432\u043e\u0440\u044f\u044e\u0442.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">\u041e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u041e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Controller<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>SessionsController<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Use Case Input Port<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ISeatService<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Use Case Interactor<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>SeatService<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Use Case Output Port<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>ISessionsRepository<\/code><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><code>Presenter<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>PostgresSessionsRepository<\/code><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u0432 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432 <code>SessionsController<\/code><\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0443 <code>ISeatService<\/code><\/p>\n<\/li>\n<li>\n<p><code>ISeatService<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f <code>SeatService<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442<\/p>\n<\/li>\n<li>\n<p><code>SeatService<\/code> \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0443 <code>ISessionsRepository<\/code><\/p>\n<\/li>\n<li>\n<p><code>ISessionsRepository<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f <code>PostgresSessionsRepository<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0411\u0414<\/p>\n<\/li>\n<\/ol>\n<h2>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0434\u0435\u0442\u0430\u043b\u044f\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u043d\u0435\u0435 \u0431\u044b\u043b\u0438 \u043e\u043f\u0443\u0449\u0435\u043d\u044b. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f &#8212; \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u043e\u043a\u0438.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0442\u0435\u0441\u0442 \u043d\u0430 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0441\u0442\u0430.<\/p>\n<pre><code class=\"cs\">public class SeatServiceTests {     private static readonly SessionInterval StubInterval = new(new DateTime(2022, 1, 1), new DateTime(2022, 2, 1));     private static readonly SeatEqualityComparer SeatComparer = new();          [Fact]     public async Task BookSeatAsync__WhenSeatIsFree__ShouldMarkSeatBooked()     {         var (sessionId, seatNumber, movieId, clientId) = ( 1, 1, 1, 2 );         var expectedSeat = new BookedSeat(seatNumber, clientId);          var session = new Session(sessionId, StubInterval, movieId, new[] {new FreeSeat(seatNumber)});         var sessionRepo = new StubSessionRepository(new[] {session});         var service = new SeatService(sessionRepo);          var actual = await service.BookSeatAsync(sessionId, seatNumber, clientId);                  Assert.Equal(expectedSeat, actual, SeatComparer);     }      [Fact]     public async Task BookSeatAsync__WhenSeatIsBought__ShouldThrowSeatBoughtException()     {         var (sessionId, seatNumber, movieId, clientId, boughtClientId) = ( 1, 1, 1, 2, 10 );         var session = new Session(sessionId, StubInterval, movieId, new[] {new BoughtSeat(seatNumber, boughtClientId)});         var sessionRepo = new StubSessionRepository(new[] {session});         var service = new SeatService(sessionRepo);          await Assert.ThrowsAnyAsync&lt;SeatBoughtException>(() => service.BookSeatAsync(sessionId, seatNumber, clientId));     }      [Fact]     public async Task BookSeatAsync__WhenSeatIsBought__ShouldSpecifyCorrectClientIdInException()     {         var (sessionId, seatNumber, movieId, clientId, boughtClientId) = ( 1, 1, 1, 2, 10 );         var session = new Session(sessionId, StubInterval, movieId, new[] {new BoughtSeat(seatNumber, boughtClientId)});         var sessionRepo = new StubSessionRepository(new[] {session});         var service = new SeatService(sessionRepo);          var exception = (SeatBoughtException) ( await Record.ExceptionAsync(() => service.BookSeatAsync(sessionId, seatNumber, clientId)) )!;         Assert.Equal(boughtClientId, exception.ClientId);     } } <\/code><\/pre>\n<h2>\u0414\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b<\/h2>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0432 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043b\u0438\u0448\u043d\u0438\u0445, \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439: \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433\u0430, \u0430\u0443\u0434\u0438\u0442\u0430, \u0441\u0431\u043e\u0440\u0430 \u043c\u0435\u0442\u0440\u0438\u043a \u0438 \u0442.\u0434.<\/p>\n<p>\u041d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u044d\u0442\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043a \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u043d\u0435\u043b\u044c\u0437\u044f, \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u0438\u0445 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u043a\u043e\u0440\u0430\u0442\u043e\u0440\u044b.<br \/> \u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c;<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0434\u043b\u044f \u043d\u0438\u0445;<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u043d\u0435\u0441\u0442\u0438 \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 &#8212; \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0431\u043e\u0440 \u043c\u0435\u0442\u0440\u0438\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u0435\u0441\u0442<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0441\u0442<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">public static class MetricsRegistry {     public static readonly Meter AppMeter = new Meter(\"CinemaBooking\", \"1.0.0\");     public static readonly Counter&lt;long> BoughtSeatsCount = AppMeter.CreateCounter&lt;long>(         name: \"seats-bought-count\",         unit: null,         description: \"\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\");      public static readonly Counter&lt;long> BookedSeatsCount = AppMeter.CreateCounter&lt;long>(         name: \"booked-seats-count\",         unit: null,         description: \"\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\");  }  public class MetricScrapperSeatService: ISeatService {     private readonly ISeatService _service;      public MetricScrapperSeatService(ISeatService service)     {         _service = service;     }      public async Task&lt;BookedSeat> BookSeatAsync(int sessionId, int place, int clientId, CancellationToken token = default)     {         var booked = await _service.BookSeatAsync(sessionId, place, clientId, token);         MetricsRegistry.BookedSeatsCount.Add(1);         return booked;     }      public async Task&lt;BoughtSeat> BuySeatAsync(int sessionId, int place, int clientId, CancellationToken token = default)     {         var bought = await _service.BuySeatAsync(sessionId, place, clientId, token);         MetricsRegistry.BoughtSeatsCount.Add(1);         return bought;     } } <\/code><\/pre>\n<h2>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0447\u0435\u043a \u0432\u0445\u043e\u0434\u0430<\/h2>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e HTTP Rest \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u041d\u043e \u0435\u0441\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0432\u0445\u043e\u0434\u0430.<\/p>\n<h3>gRPC \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441<\/h3>\n<p>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c gRPC \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u0441\u044e \u043d\u0443\u0436\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0412\u043d\u0430\u0447\u0430\u043b\u0435, \u0441\u0430\u043c <code>proto<\/code> \u0444\u0430\u0439\u043b \u0441 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u043e\u043c:<\/p>\n<pre><code>syntax = 'proto3';  option csharp_namespace = \"CinemaBooking.Grpc\";  enum OperationResultCode {    Ok = 0;    SessionNotFound = 1;    SeatNotFound = 2;    SeatBooked = 3;    SeatBought = 4; }  message BookRequest {    int32 sessionId = 1;    int32 seatNumber = 2;    int32 clientId = 3; }  message BookResponse {    OperationResultCode resultCode = 1; }  message BuyRequest {    int32 sessionId = 1;    int32 seatNumber = 2;    int32 clientId = 3; }  message BuyResponse {    OperationResultCode resultCode = 1; }  service SeatService {    rpc BookSeat(BookRequest) returns (BookResponse);    rpc BuySeat(BuyRequest) returns (BuyResponse); } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u043d\u0443\u0436\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0438\u0441.<\/p>\n<pre><code class=\"cs\">public class GrpcSeatService: SeatService.SeatServiceBase {     private readonly ISeatService _service;      public GrpcSeatService(ISeatService service)     {         _service = service;     }          public override async Task&lt;BookResponse> BookSeat(BookRequest request, ServerCallContext context)     {         var code = await ExecuteGetResultCodeAsync(t => _service.BookSeatAsync(request.SessionId, request.SeatNumber, request.ClientId, t), context.CancellationToken);         return new BookResponse() {ResultCode = code};     }      public override async Task&lt;BuyResponse> BuySeat(BuyRequest request, ServerCallContext context)     {         var code = await ExecuteGetResultCodeAsync(t => _service.BuySeatAsync(request.SessionId, request.SeatNumber, request.ClientId, t), context.CancellationToken);         return new BuyResponse() {ResultCode = code};     }      private static async Task&lt;OperationResultCode> ExecuteGetResultCodeAsync(Func&lt;CancellationToken, Task> code, CancellationToken token)     {         try         {             await code(token);             return OperationResultCode.Ok;         }         catch (SessionNotFoundException)         {             return OperationResultCode.SessionNotFound;         }         catch (SeatNotFoundException)         {             return OperationResultCode.SeatNotFound;         }         catch (SeatBoughtException)         {             return OperationResultCode.SeatBought;         }         catch (SeatBookedException)         {             return OperationResultCode.SeatBought;         }     } } <\/code><\/pre>\n<p>\u0412\u043e\u0442 gRPC \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 &#8212; \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0439 \u043c\u043e\u0440\u043e\u043a\u0438.<\/p>\n<h3>\u041a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435.<br \/> \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<br \/> \u0422\u0443\u0442 \u0442\u043e\u0436\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e: \u0432\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e &#8212; \u0432\u0441\u0435\u0433\u043e 2 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438: \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<pre><code class=\"cs\">\/\/ void Main() var arguments = CommandLineArguments.FromCommandLineArguments(args);  await using var database = GetDatabaseConnection(); var repo = new PostgresSessionRepository(database); var seatService = new SeatService(repo); var (command, sessionId, seat, clientId) = arguments;  var responseCode = 0; try {     switch (command)     {         case OperationType.Book:             try             {                 await seatService.BookSeatAsync(sessionId, seat, clientId);                 Console.WriteLine($\"\u041c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e\");             }             catch (SeatBookedException e) when (e.ClientId == clientId)             {                 Console.WriteLine($\"\u0412\u044b \u0443\u0436\u0435 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e\");             }              break;         case OperationType.Buy:             try             {                 await seatService.BuySeatAsync(sessionId, seat, clientId);                 Console.WriteLine($\"\u041c\u0435\u0441\u0442\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e\");             }             catch (SeatBoughtException e) when (e.ClientId == clientId)             {                 Console.WriteLine($\"\u0412\u044b \u0443\u0436\u0435 \u043a\u0443\u043f\u0438\u043b\u0438 \u044d\u0442\u043e \u043c\u0435\u0441\u0442\u043e\");             }              break;         default:             throw new ArgumentOutOfRangeException(nameof(command), command, \"\u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430\");     } } catch (SeatNotFoundException snf) {     Console.WriteLine($\"\u041c\u0435\u0441\u0442\u043e {snf.Seat} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e\");     responseCode = 2; } catch (SessionNotFoundException snf) {     Console.WriteLine($\"\u0421\u0435\u0430\u043d\u0441 {snf.SessionId} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\");     responseCode = 3; } catch (SeatBookedException) {     Console.WriteLine($\"\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c\");     responseCode = 4; } catch (SeatBoughtException) {     Console.WriteLine($\"\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043a\u0443\u043f\u043b\u0435\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u043c\");     responseCode = 5; }  return responseCode; <\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 3 \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>\u0422\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u0442\u0440\u044e\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u043e\u0447\u0435\u043a \u0432\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u041e\u043a\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>Serverless<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043e\u0434 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u0445\u043e\u0434\u0430 <a href=\"https:\/\/github.com\/ashenBlade\/habr-posts\/tree\/clean-architecture\/clean-architecture\/project\/src\/CinemaBooking.Console\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<h2>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e IRepository<\/h2>\n<p>\u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043f\u0440\u043e <code>IRepository<\/code>, \u0430 \u0435\u0441\u043b\u0438 \u0431\u044b\u0442\u044c \u0442\u043e\u0447\u043d\u0435\u0435, \u0442\u043e \u043f\u0440\u043e \u0435\u0433\u043e \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u043e\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">interface IRepository&lt;T> {     void Add(T item);     void Remove(T item);     T GetById(int id);     IEnumerable&lt;T> GetAll(); } <\/code><\/pre>\n<p>\u0418 \u0432\u043e\u0442 \u0434\u0430\u043b\u044c\u0448\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0430\u0434:<\/p>\n<ul>\n<li>\n<p>\u041c\u044b \u0443\u043a\u0430\u0437\u0430\u043b\u0438, \u0442\u0438\u043f ID \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e <code>T<\/code> &#8212; <code>int<\/code>, \u043d\u043e \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 <code>int<\/code>, \u0430 \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c <code>Guid<\/code> \u0438\u043b\u0438 <code>long<\/code>?<\/p>\n<\/li>\n<li>\n<p>\u0410 \u0435\u0441\u043b\u0438 \u043c\u043d\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u043c\u0435\u0442\u043e\u0434\u044b? \u0417\u0430\u0447\u0435\u043c \u0442\u0430\u0449\u0438\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435?<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a\u043e\u0439 \u0442\u0438\u043f \u043c\u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c: <code>IRepository&lt;User><\/code> \u0438\u043b\u0438 <code>IUserRepository<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 <code>IRepository&lt;User><\/code>?<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u044f \u0432 \u044d\u0442\u043e\u0442 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 <code>IRepository<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0442\u043e \u0432\u0441\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439, \u0442.\u0435. \u043c\u044b \u0436\u0435\u0441\u0442\u043a\u043e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b.<\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b <code>IxxxRepository<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b.<br \/> \u041f\u043b\u044e\u0441\u044b \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u0412\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b &#8212; \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u0438\u0448\u043d\u0438\u0439 \u043a\u043e\u0434;<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c &#8212; \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0431\u043e\u043b\u0435\u0435 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 SQL \u0437\u0430\u043f\u0440\u043e\u0441).<\/p>\n<\/li>\n<\/ul>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e. \u0420\u0435\u0448\u0438\u043b\u0438, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c <code>IRepository<\/code> \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u041e\u0441\u0442\u0430\u043b\u0441\u044f \u0432\u043e\u043f\u0440\u043e\u0441 &#8212; \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435? \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0441\u0435 \u0441\u0435\u0430\u043d\u0441\u044b \u0437\u0430 \u044d\u0442\u0443 \u043d\u0435\u0434\u0435\u043b\u044e, \u0438\u043b\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u044f \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u0437\u0430 \u0432\u0435\u0441\u044c \u043c\u0435\u0441\u044f\u0446.<\/p>\n<p>\u0415\u0441\u0442\u044c 2+ \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440,<\/p>\n<pre><code class=\"cs\">interface ISessionRepository {     int GetTotalSessionsCountForLastWeek();     int GetMostPopularSeats();     \/\/ ... } <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u0442.\u043a. \u0432 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u044d\u0442\u043e \u0437\u0430\u0442\u0440\u0443\u0434\u043d\u044f\u0435\u0442 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e &#8212; \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0411\u0414, \u0434\u0440\u0443\u0433\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c.<br \/> \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0438\u0437 \u0411\u0414, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434.<\/p>\n<pre><code class=\"cs\">[ApiController] [Route(\"admin\")] public class AdminController: ControllerBase {     private readonly SessionDbContext _context;      public AdminController(SessionDbContext context)     {         _context = context;     }      [HttpGet(\"sessions\")]     public async Task&lt;IActionResult> GetAllSessionsAsync(CancellationToken token)     {         return Ok(await _context.Sessions.Select(s => new         {             s.Id, s.Start, s.End, s.MovieId         }).ToListAsync(token));     } }    <\/code><\/pre>\n<details class=\"spoiler\">\n<summary>CQRS<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 &#8212; \u044d\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 CQRS. \u041f\u043e\u0434\u0445\u043e\u0434, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0438\u0441\u044c.<\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u043c\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u0411\u0414, \u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u0434 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438. \u0427\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044f \u0432\u0438\u0434\u0435\u043b \u0435\u0433\u043e \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c <a href=\"https:\/\/metanit.com\/sharp\/patterns\/3.9.php\" rel=\"noopener noreferrer nofollow\">\u041c\u0435\u0434\u0438\u0430\u0442\u0440<\/a>. \u042d\u0442\u043e \u043e\u0431\u0448\u0438\u0440\u043d\u0430\u044f \u0442\u0435\u043c\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0437\u0434\u0435\u0441\u044c \u044f \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u0441\u0442\u0430\u043d\u0443.<\/p>\n<p>\u041f\u043b\u044e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438, \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0411\u0414. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Redis \u0434\u043b\u044f \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u0411\u0414 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0430 \u043d\u0435 \u0447\u0435\u0440\u0435\u0437 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435; <\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0447\u0442\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f, \u0442.\u043a. \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0442\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u043c\u0430\u043f\u043f\u0438\u043d\u0433 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0432\u0441\u0435 \u0442\u0430\u043a \u0436\u0435 \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u044b, \u0442.\u043a. \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043c\u044b \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438;<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e \u0441\u0445\u0435\u043c\u043e\u0439 \u0432 \u0411\u0414, \u0442\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c ORM. \u0415\u0441\u043b\u0438 \u0441\u0445\u0435\u043c\u0430 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f (\u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0430\u0440\u0443\u0448\u0438\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0442\u0435\u043d\u0438\u044f), \u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u0430\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<br \/> \u041f\u0440\u043e CQRS \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/habr.com\/ru\/articles\/547746\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a> \u0438 <a href=\"https:\/\/habr.com\/ru\/companies\/simbirsoft\/articles\/329970\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435 \u043c\u0435\u0436\u0434\u0443 1 \u0438 2 \u043f\u0443\u043d\u043a\u0442\u043e\u043c \u043b\u0435\u0436\u0438\u0442 3-\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043f\u0430\u0442\u0442\u0435\u0440\u043d &#171;\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f&#187;.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0415\u0433\u043e \u0441\u0443\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0438\u043c\u0435\u043d\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043a\u0430\u043a <code>GetAll(Specification spec)<\/code>.<br \/> \u0422\u043e, \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 <code>Specification<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u043d\u043e \u043e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b. \u0414\u043b\u044f .NET \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0432\u0438\u0434\u0435\u043b \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>Expression<\/code>.<br \/> \u0421\u0430\u043c \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432 \u0431\u0430\u0437\u043e\u0432\u043e\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">public abstract class Specification&lt;T> {     public abstract Expression&lt;Func&lt;T, bool>> Expression { get; }      public Specification&lt;T> And(Specification&lt;T> other)     {         return new AndSpecification&lt;T>(this, other);     }      public Specification&lt;T> Or(Specification&lt;T> other)     {         return new OrSpecification&lt;T>(this, other);     }      public Specification&lt;T> Not()     {         return new NotSpecification&lt;T>(this);     }      public static implicit operator Expression&lt;Func&lt;T, bool>>(Specification&lt;T> spec) => spec.Expression; } <\/code><\/pre>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u0432\u043e\u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"cs\">public static class SessionSpecifications {     public static Specification&lt;DatabaseSession> LastDays(int days)     {         var boundary = DateTime.SpecifyKind( DateTime.Now - TimeSpan.FromDays(days), DateTimeKind.Utc);         return new GenericSpecification&lt;DatabaseSession>(session => boundary &lt; session.Start);     }      public static Specification&lt;DatabaseSession> AllFreeSeats()     {         return new GenericSpecification&lt;DatabaseSession>(session =>             session.Seats.All(seat => seat.Type == SeatType.Free));     } }  [HttpGet(\"sessions\/unvisited\")] public async Task&lt;IActionResult> GetUnvisitedSessions([FromQuery][Required] int days, CancellationToken token) {     var response = await _context.Sessions                                  .Where(SessionSpecifications.LastDays(days).And(SessionSpecifications.AllFreeSeats()))                                  .ToListAsync(token);     return Ok(response); } <\/code><\/pre>\n<p>\u042f \u043d\u0435 \u0441\u0442\u0430\u043b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c <code>GetAll(Specification&lt;Session> specification)<\/code> \u0432 <code>ISessionRepository<\/code>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043d\u0430\u0433\u0440\u043e\u043c\u043e\u0436\u0434\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u043b\u0438\u0448\u043d\u0438\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<\/div>\n<\/details>\n<\/li>\n<\/ol>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 &#8212; \u044d\u0442\u043e \u0438\u0434\u0435\u044f, \u0430 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u0418\u0434\u0435\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u0442\u043e\u0439 \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043e\u0442 \u0433\u0440\u044f\u0437\u043d\u043e\u0433\u043e \u0438 \u0442\u0443\u043f\u043e\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0438\u0440\u0430.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0430\u043c\u044b\u043c\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u0430\u043c\u0438 \u0438 \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0432 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<h3>\u0423\u0431\u0440\u0430\u0442\u044c \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f<\/h3>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 <code>Result&lt;TResult, TError><\/code>.<br \/> \u042d\u0442\u043e\u0442 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u044b\u0445 \u0438 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u0432\u0435\u0434\u044c \u0432\u0441\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u044b \u0432 \u0441\u0430\u043c\u043e\u043c <code>Result&lt;TResult, TError><\/code>.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">enum ErrorType {     SeatBooked = 0,     SeatBought = 1,     SessionNotFound = 2,     SeatNotFound = 3, }  class SeatService {     Result&lt;BookedSeat, ErrorType> BookSeat()     {         if (success)         {             return Result.FromSuccess(\/* \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 *\/);         }         else         {             return Result.FromError(\/* \u043a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438 *\/);         }     } }  class SessionsController {     public IActionResult BookSeat()     {         var result = _seatService.BookSeat();         return result.Map(             success => Ok(new SuccessDto(success)),             error   => BadRequest(new ErrorDto(error)));     } } <\/code><\/pre>\n<h3>\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043d\u0430 \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439<\/h3>\n<p>\u041a\u043b\u0430\u0441\u0441 <code>Seat<\/code> &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u0441 2 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 <code>Buy<\/code> \u0438 <code>Book<\/code>. \u041d\u043e \u0441\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043d\u0438\u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 <code>ISeatVisitor<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u0430\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c.<\/p>\n<p>\u042f \u0432\u044b\u0431\u0440\u0430\u043b \u043f\u043e\u0434\u0445\u043e\u0434 \u0441 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 <code>Buy<\/code> \u0438 <code>Book<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a:<\/p>\n<ul>\n<li>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0430 \u043c\u0435\u0441\u0442 \u043d\u0430\u0448\u0430 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u044f\u0432\u043d\u043e \u043e\u0442\u0440\u0430\u0436\u0435\u043d\u0430 \u0432 \u043a\u043e\u0434\u0435 (\u0441\u043c. <a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2011\/09\/30\/Screaming-Architecture.html\" rel=\"noopener noreferrer nofollow\">\u043a\u0440\u0438\u0447\u0430\u0449\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/a>);<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u044c \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u043b\u0438 \u0431\u0435\u0437 \u0431\u043e\u043b\u0435\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043f\u043e\u0434\u0442\u0438\u043f\u044b <code>Seat<\/code>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0410\u043d\u0435\u043c\u0438\u0447\u043d\u044b\u0435\/\u0431\u043e\u0433\u0430\u0442\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438<\/h3>\n<p>\u041d\u0430\u0448\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b &#8212; \u0431\u043e\u0433\u0430\u0442\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438: \u043e\u043d\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u043e \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u0438 \u0430\u043d\u0435\u043c\u0438\u0447\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0435\u0437 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<p>\u0423 \u044d\u0442\u0438\u0445 2 \u043b\u0430\u0433\u0435\u0440\u0435\u0439 \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430 \u0430\u043d\u0435\u043c\u0438\u0447\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 &#8212; \u044d\u0442\u0430 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Anemic_domain_model\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a>;<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430 \u0431\u043e\u0433\u0430\u0442\u044b\u0435 &#8212; <a href=\"https:\/\/dev.to\/crovitz\/have-you-anemic-or-rich-domain-model-2ala\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u0430<\/a>.<\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043a \u0431\u043e\u0433\u0430\u0442\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u043a\u043e\u0434\u0435 \u044f\u0441\u043d\u0435\u0435 (\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435) \u0438 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (<a href=\"https:\/\/codeopinion.com\/always-valid-domain-model\/\" rel=\"noopener noreferrer nofollow\">Always Valid Model<\/a>).<\/p>\n<h3>\u0420\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u0435\u0439<\/h3>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044f \u0440\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u044f \u043f\u043e\u0440\u0442\u044b \u0438 \u0430\u0434\u0430\u043f\u0442\u0435\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438, \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u043c\u0438 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\/\u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 &#8212; \u043d\u0438 \u043e\u0442 \u043a\u043e\u0433\u043e \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442;<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\/\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 &#8212; \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u0433\u043e;<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f &#8212; \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0434\u043e\u043c\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u044b. \u041e\u0431\u0437\u043e\u0440 \u043d\u0430 \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u044d\u0442\u043e\u0439 <a href=\"https:\/\/habr.com\/ru\/articles\/683456\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0442\u0430\u0442\u044c\u0435<\/a>.<\/p>\n<h3>\u041d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u041e\u041e\u041f \u044f\u0437\u044b\u043a\u0438 \u044d\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442<\/h3>\n<p>\u042f .NET \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0432\u0435\u043b \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430 C#:<\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u044b (.csproj);<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b (<code>interface<\/code>);<\/p>\n<\/li>\n<li>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438 \u0441 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 \u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430\u043c\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u043e \u044d\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u042f\u041f \u043d\u0435\u043b\u044c\u0437\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435.<\/p>\n<p>\u0412\u043e\u0437\u044c\u043c\u0435\u043c \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u044f\u0437\u044b\u043a F#. \u042d\u0442\u0438 \u0441\u0430\u043c\u044b\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u044b \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0410\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0435\u043c (<code>module<\/code>).<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 F#<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"fsharp\">namespace CinemaBooking.Domain.Functional  open Microsoft.FSharp.Core   \/\/ \u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u043c\u0435\u0440\u0430 \u043c\u0435\u0441\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 module SeatNumber =     type SeatNumber = private SeatNumber of int      let number (seat: SeatNumber) : int =         match seat with         | SeatNumber(n) -> n          let create number =         if number &lt; 1 then             Option.None         else             Option.Some(SeatNumber number)  type ClientId = int32  module Seat =     open SeatNumber          \/\/ \u0421\u0430\u043c\u043e \u043c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0430\u0437\u043c\u0435\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (Discriminated Union)     type Seat =         | FreeSeat of Number: SeatNumber         | BookedSeat of Number: SeatNumber * ClientId: ClientId         | BoughtSeat of Number: SeatNumber * ClientId: ClientId      let number seat =         match seat with         | FreeSeat number -> number         | BookedSeat(number, _) -> number         | BoughtSeat(number, _) -> number      \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u0438-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b     let free (number: SeatNumber) : Seat = FreeSeat number     let booked (number: SeatNumber, clientId: ClientId) : Seat = BookedSeat(number, clientId)     let bought (number: SeatNumber, clientId: ClientId) : Seat = BoughtSeat(number, clientId)      type TransitionError =         | SeatBought of ClientId: ClientId         | SeatBooked of ClientId: ClientId      \/\/ \u041f\u043e\u043a\u0443\u043f\u043a\u0430 \u043c\u0435\u0441\u0442\u0430     let buy clientId seat =         match seat with         | FreeSeat number -> Ok(BoughtSeat(number, clientId))         | BookedSeat(number, bookedClientId) when (bookedClientId = clientId) -> Ok(BoughtSeat(number, clientId))         | BookedSeat(_, bookedClientId) -> Error(TransitionError.SeatBooked bookedClientId)         | BoughtSeat(_, boughtClientId) when (clientId = boughtClientId) -> Ok seat         | BoughtSeat(_, boughtClientId) -> Error(TransitionError.SeatBought boughtClientId)      \/\/ \u0411\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430     let book clientId seat : Result&lt;Seat, TransitionError> =         match seat with         | FreeSeat number -> Ok(BookedSeat(number, clientId))         | BookedSeat(_, bookedClientId) when (clientId = bookedClientId) -> Ok seat         | BookedSeat(_, bookedClientId) -> Error(TransitionError.SeatBooked bookedClientId)         | BoughtSeat(_, boughtClientId) -> Error(TransitionError.SeatBought boughtClientId)   module Session =     open Seat          type SessionId = int32      type Session =             { Id: SessionId               Seats: Seat.Seat list }      \/\/ \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0435\u0430\u043d\u0441     let create id seats : Session = { Id = id; Seats = seats }          \/\/ \u041d\u0430\u0439\u0442\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0435     let tryFindSeat seatNumber session =         List.tryFind (fun seat -> number seat = seatNumber) session.Seats          \/\/ \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0435     let setSeat session seat =         {session with Seats = session.Seats                                      |> List.map (fun s -> if number s = number seat then seat else s)}          type OperationError =         | SeatNotFound         | SeatBooked of ClientId: ClientId         | SeatBought of ClientId: ClientId      let makeSeatTransition (operation: Seat -> Result&lt;Seat, TransitionError>) seat =         match operation seat with         | Ok newSeat -> Ok newSeat         | Error e -> match e with                      | TransitionError.SeatBought clientId -> Error (OperationError.SeatBought clientId)                      | TransitionError.SeatBooked clientId -> Error (OperationError.SeatBooked clientId)          \/\/ \u041f\u043e\u043a\u0443\u043f\u043a\u0430 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0435     let buy session seatNumber clientId =         match session |> tryFindSeat seatNumber with         | None -> Error SeatNotFound         | Some seat -> seat                         |> makeSeatTransition (buy clientId)                         |> Result.map (setSeat session)          \/\/ \u0411\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0435     let book session seatNumber clientId =         match session |> tryFindSeat seatNumber with         | None -> Error SeatNotFound         | Some seat -> seat                         |> makeSeatTransition (book clientId)                         |> Result.map (setSeat session)    module SeatService =         open Session          \/\/ \u0412\u043c\u0435\u0441\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 - \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438     type SessionFinder = SessionId -> Session option     type SessionUpdater = Session -> Unit          type ServiceError =         | SessionNotFound         | SeatNotFound         | SeatBooked of ClientId: ClientId         | SeatBought of ClientId: ClientId              let toOperationError e =         match e with         | OperationError.SeatNotFound -> ServiceError.SeatNotFound         | OperationError.SeatBooked clientId -> ServiceError.SeatBooked clientId         | OperationError.SeatBought clientId -> ServiceError.SeatBought clientId          \/\/ \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438     let book sessionId number clientId sessionFinder sessionUpdater =         let session = sessionFinder sessionId         match session with         | None -> Error SessionNotFound         | Some session -> book session number clientId                           |> Result.mapError toOperationError                           |> Result.map (fun s -> sessionUpdater s; s)                                 let buy sessionId number clientId sessionFinder sessionUpdater =         let session = sessionFinder sessionId         match session with         | None -> Error SessionNotFound         | Some session -> buy session number clientId                           |> Result.mapError toOperationError                           |> Result.map (fun s -> sessionUpdater s; s) <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/h2>\n<ul>\n<li>\n<p><a href=\"https:\/\/www.chitai-gorod.ru\/product\/chistaya-arhitektura-iskusstvo-razrabotki-programmnogo-obespecheniya-2640391\" rel=\"noopener noreferrer nofollow\">&#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187; \u0420\u043e\u0431\u0435\u0440\u0442\u0430 \u0424\u0430\u0443\u043b\u0435\u0440\u0430<\/a><\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 <a href=\"https:\/\/github.com\/ashenBlade\/habr-posts\/tree\/clean-architecture\/clean-architecture\/project\" rel=\"noopener noreferrer nofollow\">GitHub<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/companies\/simbirsoft\/articles\/329970\/\" rel=\"noopener noreferrer nofollow\">\u041e\u0441\u043d\u043e\u0432\u044b CQRS<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/683456\/\" rel=\"noopener noreferrer nofollow\">\u041f\u043e\u0434\u0445\u043e\u0434\u044b \u043a \u0434\u0435\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/martinfowler.com\/tags\/domain%20driven%20design.html\" rel=\"noopener noreferrer nofollow\">DDD \u043e\u0442 \u041c\u0430\u0440\u0442\u0438\u043d\u0430 \u0424\u0430\u0443\u043b\u0435\u0440\u0430<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/784922\/\"> https:\/\/habr.com\/ru\/articles\/784922\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e!<\/p>\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043b \u0434\u0440\u0443\u0433\u0430 \u0441 \u043f\u043e\u043d\u044f\u0442\u0438\u0435\u043c &#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;. \u0421 \u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043e\u043d \u0447\u0430\u0441\u0442\u043e \u0430\u0442\u0430\u043a\u043e\u0432\u0430\u043b \u043c\u0435\u043d\u044f \u0432\u043e\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 &#171;\u0410 \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c? \u0410 \u043a\u0430\u043a \u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c?&#187;. \u0412 \u043e\u0434\u0438\u043d \u043c\u043e\u043c\u0435\u043d\u0442 \u0445\u043e\u0442\u0435\u043b \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0438\u043d\u0443\u0442\u044c \u0435\u043c\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u0441 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u043c, \u043d\u043e \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u043f\u0435\u0440\u0435\u0447\u0438\u0442\u0430\u0432 \u043a\u043d\u0438\u0433\u0443 \u0420\u043e\u0431\u0435\u0440\u0442\u0430 \u041c\u0430\u0440\u0442\u0438\u043d\u0430 <a href=\"https:\/\/www.chitai-gorod.ru\/product\/chistaya-arhitektura-iskusstvo-razrabotki-programmnogo-obespecheniya-2640391\" rel=\"noopener noreferrer nofollow\">&#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;<\/a>, \u043e\u0441\u0432\u0435\u0436\u0438\u0432 \u0441\u0432\u043e\u0438 \u0437\u043d\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0432\u0448\u0438\u0441\u044c \u0432 \u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0438, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u044e.<\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0447\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u0427\u0438\u0441\u0442\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0444\u0440\u0430\u0437\u043e\u0439 &#8212; <code>\u0441\u0442\u0440\u043e\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u043e\u043a\u0440\u0443\u0433 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438<\/code>:<\/p>\n<ul>\n<li>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432\u0441\u044f\u043a\u0438\u043c\u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430\u043c\u0438, \u0411\u0414, HTTP \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0442.\u0434.;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e \u043f\u043e\u0432\u043e\u0434\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043c\u0438\u0440\u043e\u043c \u043e\u0442\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442\u0441\u044f, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0430\u0441\u0442\u043d\u044b\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 \u044d\u0442\u043e\u0433\u043e:<\/p>\n<ol>\n<li>\n<p>\u041d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432\/\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u043e\u0432;<\/p>\n<\/li>\n<li>\n<p>\u041c\u044b \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043d\u0438 \u043e \u043a\u0430\u043a\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 &#8212; \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0447\u0435\u0433\u043e-\u043b\u0438\u0431\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043a \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e &#8212; \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438\/\u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>Domain first \u043f\u043e\u0434\u0445\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0435\u0441\u0442\u044c 3 \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p>Code first<\/p>\n<\/li>\n<li>\n<p>Database first<\/p>\n<\/li>\n<li>\n<p>Model first<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f API \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432:<\/p>\n<ul>\n<li>\n<p>Code first<\/p>\n<\/li>\n<li>\n<p>Contract first<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u044f \u0431\u044b \u0434\u0430\u043b \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 <code>Domain-first<\/code><\/p>\n<\/div>\n<\/details>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u044d\u0442\u0443 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 &#171;\u0427\u0438\u0441\u0442\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430&#187;:<\/p>\n<figure class=\"\">\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043f\u044b\u0442\u0430\u044e\u0441\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0447\u0442\u043e \u043d\u0430 \u043d\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442.<\/p>\n<p>\u0421\u043b\u0435\u0432\u0430 \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u043e\u0431\u0449\u0438\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043d\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041c\u043e\u0434\u0443\u043b\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u043e \u0441\u043b\u043e\u044f\u043c (\u0441\u043d\u0438\u0437\u0443 \u0432\u0432\u0435\u0440\u0445):<\/p>\n<ol>\n<li>\n<p>Entities <\/p>\n<ul>\n<li>\n<p>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0441\u0430\u043c\u0443\u044e \u0432\u0430\u0436\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443\/\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0440\u0430\u0441\u0447\u0435\u0442 \u0443\u0433\u043b\u0430 \u0431\u0440\u043e\u0441\u043a\u0430 \u0441\u043d\u0430\u0440\u044f\u0434\u0430<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>Use Cases <\/p>\n<ul>\n<li>\n<p>\u041d\u0430\u0448\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b<\/p>\n<\/li>\n<li>\n<p>\u042d\u0442\u043e\u0442 \u0441\u043b\u043e\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 &#8212; \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0448\u0435\u0439 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u0443\u0435\u0442 Entities<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u0443\u0433\u043b\u0430 \u0443\u0434\u0430\u0440\u0430 \u0432 \u0431\u0438\u043b\u044c\u044f\u0440\u0434\u0435 \u0438 \u0442\u0440\u0430\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0432\u044b\u0441\u0442\u0440\u0435\u043b\u0430 \u0438\u0437 \u043f\u0443\u0448\u043a\u0438<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b\/\u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0435\u0440\u044b <\/p>\n<ul>\n<li>\n<p>\u0422\u0435, \u0441 \u043a\u0435\u043c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: MVC \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b, \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430 \u0434\u043b\u044f gRPC, \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f (MVVM)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>UI, \u0411\u0414, \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 <\/p>\n<ul>\n<li>\n<p>\u042d\u0442\u043e \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u043c\u0438\u0440<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435 \u0438\u0437 \u043a\u043d\u0438\u0433\u0438<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u043a\u043d\u0438\u0433\u0435 \u0420\u043e\u0431\u0435\u0440\u0442 \u0424\u0430\u0443\u043b\u0435\u0440 \u0434\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>Critical Business Rules &#8212; \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u0437\u0430\u043a\u043e\u043d\u044b, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438 \u0431\u0435\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c<\/p>\n<blockquote>\n<p>&#8230; they are critical to the business itself, and would exist even if there were no system to automate them<\/p>\n<\/blockquote>\n<\/li>\n<li>\n<p>Critical Business Data &#8212; \u044d\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u044d\u0442\u0438\u0445 \u0441\u0430\u043c\u044b\u0445 Critical Business Rules<\/p>\n<blockquote>\n<p>&#8230; the data that would exist even if the system were not automated<\/p>\n<\/blockquote>\n<\/li>\n<\/ul>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044e \u0441\u0430\u043c\u043e\u0433\u043e <code>Entity<\/code>:<\/p>\n<blockquote>\n<p>Entity &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 Critical Business Rules \u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u044b Critical Business Data<\/p>\n<\/blockquote>\n<p>\u0410 <code>Use Cases<\/code> &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u0443\u044e\u0442 \u044d\u0442\u0438\u043c\u0438 <code>Entity<\/code>, \u0442\u0430\u043a \u043a\u0430\u043a \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435.<\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0434\u0430\u0435\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b:<\/p>\n<ul>\n<li>\n<p>Critical Business Rules &#8212; \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0441\u0447\u0435\u0442\u0430 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u043e\u0439 \u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u043e \u043a\u0440\u0435\u0434\u0438\u0442\u0443;<\/p>\n<\/li>\n<li>\n<p>Critical Business Data &#8212; \u044d\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430: \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0430\u044f \u0441\u0442\u0430\u0432\u043a\u0430, \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u043b\u043e\u0433\u0430, \u0432\u0440\u0435\u043c\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0432\u0430\u043d\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>Entity &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e \u0444\u043e\u0440\u043c\u0443\u043b\u0435 <code>Critical Business Rules<\/code> \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043d\u0443\u044e \u0441\u0442\u0430\u0432\u043a\u0443 \u043f\u043e <code>Critical Business Data<\/code>;<\/p>\n<\/li>\n<li>\n<p>Use Case &#8212; \u044d\u0442\u043e \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0442\u043e\u0433\u043e, \u043a\u0442\u043e \u0445\u043e\u0447\u0435\u0442 \u0432\u0437\u044f\u0442\u044c \u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u0438\u043b\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0432\u0437\u043d\u043e\u0441\u0443.<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c 2 \u0432\u0435\u0449\u0438:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 <strong>\u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/strong> &#8212; \u043d\u0435 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u0442\u043e, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438);<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0434\u0443\u0442 \u0441\u0442\u0440\u043e\u0433\u043e \u043e\u0442 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u043b\u043e\u0435\u0432 \u043a\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c &#8212; \u043e\u0434\u0438\u043d \u043c\u043e\u0434\u0443\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0441\u0441\u044b\u043b\u0430\u0442\u044c \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u043e \u044d\u0442\u043e\u0439 \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u043e\u043d \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0438\u0436\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u043f\u0440\u0430\u0432\u0430 \u0438\u0434\u0435\u0442 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 &#8212; \u0442\u043e, \u043a\u0430\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u0435\u0431\u044f \u0432\u0435\u0441\u0442\u0438 \u0432 \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 UML \u0438 \u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438.<\/p>\n<p>\u0427\u0442\u043e \u043d\u0430 \u043d\u0435\u0439 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><code>Controller<\/code> &#8212; \u044d\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 3 \u0443\u0440\u043e\u0432\u043d\u044f, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043e\u0431\u0449\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u044b;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Input Port<\/code> &#8212; \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0430\u0448\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f &#8212; \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Interactor<\/code> &#8212; \u044d\u0442\u043e \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>Use Case Input Port<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443;<\/p>\n<\/li>\n<li>\n<p><code>Use Case Output Port<\/code> &#8212; \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414, \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0438\u0441\u044c\u043c\u0430 \u0438 \u0442.\u0434.;<\/p>\n<\/li>\n<li>\n<p><code>Presenter<\/code> &#8212; \u044d\u0442\u043e \u0441\u0430\u043c\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <code>Use Case Output Port<\/code>. \u0418\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c Presenter, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043d\u043e\u0432\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 SQL \u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u043a\u0432\u043e\u0437\u044c \u0432\u0441\u044e \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0443, \u043e\u0442 <code>Controller<\/code> \u043a <code>Presenter<\/code>, \u043a\u0430\u0441\u0430\u044f\u0441\u044c <code>Use Case Interactor<\/code>, \u0434\u0432\u0438\u0436\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u0435\u043b\u043a\u0430. \u042d\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f &#8212; \u043a\u0442\u043e-\u043a\u043e\u0433\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442.<\/p>\n<p>\u041f\u0440\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e\u0442\u043e\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a: <code>Controller<\/code> -> <code>Use Case Interactor<\/code> -> <code>Presenter<\/code>.<br \/> \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<ol>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0441\u0434\u0435\u043b\u0430\u043b \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432\u044b\u0437\u0432\u0430\u043b \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0430 \u0434\u043e\u043c\u0435\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435;<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u043c\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u044b\u0437\u0432\u0430\u043b \u043c\u0435\u0442\u043e\u0434 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043d\u043e\u0432\u0438\u043b \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0442\u043e, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u043a \u043a\u043e\u043d\u0446\u0443 \u0441\u0442\u0430\u043d\u0435\u0442 \u044f\u0441\u043d\u0435\u0435.<\/p>\n<h2>\u0420\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u0443<\/h2>\n<h3>\u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c<\/h3>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0438\u0434\u0435\u044e \u0447\u0438\u0441\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b.<\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f: \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043b\u044f \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u0431\u0438\u043b\u0435\u0442\u043e\u0432 \u0432 \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0435. \u0412\u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u0439\u043c\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u0438\u0440\u0430.<\/p>\n<p><em>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u0430 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439. 3.. 2.. 1.. \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u044b<\/em><br \/> <em>\u041f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438. 3.. 2.. 1.. \u041f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u0430\u044f \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0430<\/em><\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0444\u0438\u043b\u044c\u043c\u043e\u0432 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u0441\u0435\u0430\u043d\u0441\u044b;<\/p>\n<\/li>\n<li>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0441\u0435\u0430\u043d\u0441 \u0435\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0435\u0441\u0442;<\/p>\n<\/li>\n<li>\n<p>\u041e\u0434\u043d\u043e \u043c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043a\u0443\u043f\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0447\u0435\u043b\u043e\u0432\u0435\u043a;<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e \u0441\u0435\u0430\u043d\u0441\u0430 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u044b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e;<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043a\u0443\u043f\u0438\u0442\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043b\u0438\u0431\u043e \u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0437\u0430 \u043d\u0438\u043c.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0430\u0432\u0438\u043b \u043d\u0435\u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0445\u0432\u0430\u0442\u0438\u0442.<\/p>\n<blockquote>\n<p>\u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043a\u0440\u043e\u043c\u0435 \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u043e\u043a\u0443\u043f\u043a\u0438 \u043c\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c: \u043d\u0435 \u0437\u043d\u0430\u0435\u043c \u043a\u0430\u043a \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0441\u0435\u0430\u043d\u0441\u044b, \u043e\u0442\u043a\u0443\u0434\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u0438 \u0442.\u0434.<\/p>\n<\/blockquote>\n<h3>\u041c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043c\u0435\u0442\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u0435\u0435, \u0441 \u0447\u0435\u043c \u043c\u044b \u0438\u043c\u0435\u0435\u043c \u0434\u0435\u043b\u043e, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u041d\u0430\u0448\u0430 \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 &#8212; \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u043a\u0443\u043f\u0430\u0442\u044c \u043c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u043f\u043e\u0441\u0435\u0442\u0438\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0441\u0435\u0430\u043d\u0441\u0430\u0445. \u041f\u043e \u0438\u0434\u0435\u0435, \u0441\u0435\u0430\u043d\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043f\u043e\u043a\u0430\u0437\u0430 \u0444\u0438\u043b\u044c\u043c\u0430, \u0441\u0430\u043c \u0444\u0438\u043b\u044c\u043c, \u0437\u0430\u043b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. (!) \u041d\u043e \u043d\u0430\u0448\u0430 \u043e\u0431\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c &#8212; \u044d\u0442\u043e \u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0441\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043b\u044f \u043d\u0430\u0441 \u0441\u0435\u0430\u043d\u0441 &#8212; \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0441\u0442 \u0441 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0430\u043d\u0441 \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">class Session {     \/\/\/ &lt;summary>     \/\/\/ \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0435\u0430\u043d\u0441\u0430     \/\/\/ &lt;\/summary>     public int Id { get; }         private readonly Seat[] _seats;          \/\/\/ &lt;summary>     \/\/\/ \u041c\u0435\u0441\u0442\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0430\u043d\u0441\u0430      \/\/\/ &lt;\/summary>     public IReadOnlyCollection&lt;Seat> Seats => _seats;          public Session(SessionInterval interval, int movieId, IEnumerable&lt;Seat> seats)     {         ArgumentNullException.ThrowIfNull(interval);         ArgumentNullException.ThrowIfNull(seats);                  Interval = interval;         MovieId = movieId;         _seats = BuildSeatsArray(seats);     }      private static Seat[] BuildSeatsArray(IEnumerable&lt;Seat> seats)     {         var array = seats.ToArray();         for (var i = 0; i &lt; array.Length; i++)         {             if (array[i] == null!)             {                 throw new ArgumentNullException(nameof(seats), $\"\u041e\u0431\u044a\u0435\u043a\u0442 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 {i} \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0431\u044b\u043b null\");             }         }          return array;     }          \/\/ ... } <\/code><\/pre>\n<p>\u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u0440\u0443\u0448\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u2014 \u0441\u0430\u043c\u0438\u043c \u043d\u0430\u043a\u043e\u0441\u044f\u0447\u0438\u0442\u044c:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0437\u043e\u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430, \u0433\u0434\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0432\u0445\u043e\u0434\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b;<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0442\u0430\u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u2014 \u0432\u0441\u0435 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u043d\u0430\u0440\u0443\u0436\u0443 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 (get-only, IReadOnlyCollection);<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043c\u0435\u0441\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>Seat<\/code>, \u043d\u043e \u0435\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0435\u0449\u0435 \u043d\u0435 \u0431\u044b\u043b\u043e, \u2014 \u044d\u0442\u043e \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>\u041c\u0435\u0441\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c 3 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f: \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e, \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u043e. \u041f\u0440\u0438\u0447\u0435\u043c, \u0435\u0441\u043b\u0438 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438\u043b\u0438 \u043a\u0443\u043f\u043b\u0435\u043d\u043e, \u0442\u043e \u0417\u0410 \u041a\u0415\u041c-\u0422\u041e. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0443\u043c\u0430\u043b\u0438 \u043f\u0440\u043e \u0411\u0414, \u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">enum SeatType {     Free = 0,     Booked = 1,     Bought = 2, }  class Seat {     public SeatType Type { get; set; }     public int SessionId { get; set; }     public Session Session { get; set; }     public int Number { get; set; }     public int? ClientId { get; set; } } <\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 POCO \u043a\u043b\u0430\u0441\u0441, \u0433\u0434\u0435 \u0432\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0430 \u043d\u0430\u0440\u0443\u0436\u0443.<\/p>\n<p>\u041c\u044b, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0438 \u043b\u043e\u0433\u0438\u043a\u0438.<br \/> \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f <code>Id<\/code> \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u0441\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e:<\/p>\n<pre><code class=\"cs\">class Seat {     public bool TryGetClientIdBooked(out int clientId)     {         if (Type == SeatType.Booked)         {             clientId = ClientId.Value;             return true;         }         clientId = default;         return true;     } } <\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043b\u043e\u0445 \u0442\u0435\u043c, \u0447\u0442\u043e:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u0438 \u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u043e\u0431\u0440\u043e\u0441\u043e\u0432\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442: \u043c\u043e\u0436\u043d\u043e \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432 <code>null<\/code> \u0434\u043b\u044f \u043a\u0443\u043f\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u0423 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u043c\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b: \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Id \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430;<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0435 <code>ClientId<\/code> \u0443 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0435\u0449\u0438: \u0442\u043e\u0442 \u043a\u0442\u043e \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u0438 \u043a\u0442\u043e \u043a\u0443\u043f\u0438\u043b \u043c\u0435\u0441\u0442\u043e &#8212; \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u044d\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u043e\u044d\u0442\u0430\u043f\u043d\u043e \u0438 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 2 \u043f\u0443\u043d\u043a\u0442\u0430. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c &#8212; \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430. \u041f\u0435\u0440\u0435\u043f\u0438\u0448\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">abstract class Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041d\u043e\u043c\u0435\u0440 \u043c\u0435\u0441\u0442\u0430 \u0432 \u0437\u0430\u043b\u0435     \/\/\/ &lt;\/summary>     public int Number { get; }     protected internal Seat(int number)     {         if (number &lt; 1)         {             throw new ArgumentOutOfRangeException(nameof(number), number, \"\u041d\u043e\u043c\u0435\u0440 \u043c\u0435\u0441\u0442\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\");         }         Number = number;     } }   class FreeSeat: Seat {     public FreeSeat(int number) : base(number)     { } }  class BookedSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int ClientId { get; }      public BookedSeat(int number, int clientId) : base(number)     {         ClientId = clientId;     } }  class BoughtSeat: Seat {     \/\/\/ &lt;summary>     \/\/\/ \u041a\u043b\u0438\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043a\u0443\u043f\u0438\u043b \u043c\u0435\u0441\u0442\u043e     \/\/\/ &lt;\/summary>     public int ClientId { get; }      public BoughtSeat(int number, int clientId) : base(number)     {         ClientId = clientId;     } } <\/code><\/pre>\n<p>\u0421\u0442\u043e\u0438\u0442 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<ul>\n<li>\n<p>\u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u0435\u0441\u0442\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u0442;<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0436\u043d\u043e \u0443\u0442\u0432\u0435\u0440\u0436\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0442\u0438\u043f\u044b \u043c\u0435\u0441\u0442<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-364721","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/364721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=364721"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/364721\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=364721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=364721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=364721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}