ืื Raiffeisenbank .NET ืืขืืืขืืึธืคึผืขืจ ืงืื ืืืื ืฆื ืืขืงืืฆืขืจ ืึธืคึผืฉืึทืฆื ืื ืืื ืืึทืื ืคืื ViennaNET. ืืืขืื ืืื ืืื ืืืึธืก ืืืจ ืืขืงืืืขื ืฆื ืืขื,
ืืื ืืขื ืึทืจืืืงื, ืืืจ ืืืขืื ืืืจืืืืื ื ืึธื-ืฆื-ืืืื-ืืืืจืืื ืืืืืจืขืจืื ืคึฟืึทืจ ืืจืืขืื ืืื ืคืื ืื ืืขืจืืขืืืืื ืืจืึทื ืืึทืงืฉืึทื ื, ืงืืื ืืื ืืึทืืึทืืืืกืื, ืืืึธืก ืงืขื ืขื ืืืื ืืขืคึฟืื ืขื ืืื ืืื ืืืขืจ GitHub ืจืืคึผืึทืืึทืืึธืจื (
ViennaNET.Sagas
ืืืขื ืึท ืคึผืจืืืขืงื ืกืืืืืฉืื ืฆื DDD ืืื ืืืงืจืึธืกืขืจืืืืก ืึทืจืงืึทืืขืงืืฉืขืจ, ืืืขื ืืขืฉืขืคื ืืึธืืืง ืืื ืคืื ืื ืืขืจืืขืืืืื ืืืืขืจ ืคืึทืจืฉืืืขื ืข ืืึทืืื ืื ืืก, ืึท ืคึผืจืึธืืืขื ืขืจืืืืึทื ืฉืืึทืืืช ืฆื ืื ื ืืื ืฆื ืื ืกืืจืืืขื ื ืึท ืคืื ืื ืืขืจืืขืืืืื ืืจืึทื ืกืึทืงืืืึธื ืืขืงืึทื ืืืึทื, ืืืืึทื ืคืืืข ืกืื ืขืจืืึธืื ืึธืคื ืืืืจืงื ืขืืืขืืข ืืึธืืืืื ื ืืื ืึทืืึธื. ืืืจ ืงืขื ืขื ืืึทืงืืืขื ืืึทืงืึทื ื ืืื ืึทืืึท ืืขืงืึทื ืืืึทืื ืืื ืืขืจ ืืขืืึทื, ืืืฉื,
ืืื ืืื ืืืขืจ ืคึผืจืึทืืืฉืขืงืก, ืืืจ ืืึธืื ืืืคึผืืึทืืขื ืึทื ืึท ืคึผืฉืื ืึธืืขืจ ื ืืฆืืง ืืขืงืึทื ืืืึทื: ืึท ืกืึทืืข, ืึธืืขืจ ืืึทื ืฅ ืึทื ืึธืจืงืขืกืืจืึทืืืึธื-ืืืืืจื ืกืึทืืข. ืื ืขืกืึทื ืก ืืื ืืื ืืืื: ืขืก ืืื ืึท ืืืืขืจ ืืขืฉืขืคื ืกืฆืขื ืึทืจ ืืื ืืืึธืก ืขืก ืืื ื ืืืืืง ืฆื ืกืึทืงืืืขื ืืฉืึทืื ืืืจืืคืืจื ืึทืคึผืขืจืืืฉืึทื ื ืืื ืคืึทืจืฉืืืขื ืข ืืึทืืื ืื ืืก, ืืื ืืืื ืขืก ืืขื ืขื ืงืืื ืคืจืืืืขืืขื ืืื ืงืืื ืฉืจืื, ืขืก ืืื ื ืืืืืง ืฆื ืจืืคื ืื ืจืึธืืืืึทืง ืคึผืจืึธืฆืขืืืจ ืคึฟืึทืจ ืึทืืข ืื ืคืจืืขืจืืืงืข ืกืืขืคึผืก. ืฆืืืขืฉืืขืื. ืืืื, ืืื ืื ืกืืฃ ืคืื ืื ืกืึทืืข, ืจืึทืืึทืจืืืึทืก ืคืื ืืฆืืื, ืืืจ ืืึทืงืืืขื ืงืึธื ืกืืกืืขื ื ืืึทืื ืืื ืึทืืข ืืึธืืืืื ื.
ืืื ืืืขืจ ืืืคึผืืึทืืขื ืืืืฉืึทื ืืื ื ืึธื ืืขืืืื ืืื ืืืึทื ืืงืขืจืืืง ืคืึธืจืขื ืืื ืืื ื ืืฉื ืืืื ืฆื ืื ื ืืฆื ืคืื ืงืืื ืืขืืืึธืืก ืคืื ืื ืืขืจืึทืงืฉืึทื ืืื ืื ืืขืจืข ืืึทืืื ืื ืืก. ืขืก ืืื ื ืืฉื ืฉืืืขืจ ืฆื ื ืืฆื: ื ืึธืจ ืืึทืื ืึท ืึธืคึผืฉืืึทืืืื ื ืคืื ืื ืืึทืืข ืึทืืกืืจืึทืงื ืงืืึทืก SagaBase<T>, ืืื T ืืื ืืืื ืงืึธื ืืขืงืกื ืงืืึทืก ืืื ืืืึธืก ืืืจ ืงืขื ืขื ืงืจืึธื ืื ืขืจืฉื ืืึทืื ื ืืืืืง ืคึฟืึทืจ ืื ืกืึทืืข ืฆื ืึทืจืืขืื, ืืื ืขืืืขืืข ืื ืืขืจืืืืืื ืจืขืืืืืึทืื. ืืขืจ ืงืึธื ืืขืงืกื ืืืึทืฉืคึผืื ืืืขื ืืืื ืืืจืืืขืืื ืืขื ืืืจื ืึทืืข ืกืืขืคึผืก ืืขืฉืึทืก ืืืจืืคืืจืื ื. ืกืึทืืึท ืืื ืืื ืึท ืกืืึทืืขืืขืกืก ืงืืึทืก, ืึทืืื ืืขืจ ืืืึทืฉืคึผืื ืงืขื ืขื ืืืื ืืขืฉืืขืื ืืื DI ืืื ืึท ืกืื ืืืขืืึธื ืฆื ืืึทืงืืืขื ืื ื ืืืืืง ืืืคึผืขื ืืึทื ืกืื.
ืืืึทืฉืคึผืื ืึทื:
public class ExampleSaga : SagaBase<ExampleContext>
{
public ExampleSaga()
{
Step("Step 1")
.WithAction(c => ...)
.WithCompensation(c => ...);
AsyncStep("Step 2")
.WithAction(async c => ...);
}
}
ืืืึทืฉืคึผืื ืจืืคื:
var saga = new ExampleSaga();
var context = new ExampleContext();
await saga.Execute(context);
ืืึทื ืฅ ืืืืฉืคืืื ืคืื ืคืึทืจืฉืืืขื ืข ืืืคึผืืึทืืึทื ืฅ ืงืขื ืขื ืืืื ืืืืื
ViennaNET.Orm.*
ื ืกืืื ืคืื ืืืืืจืขืจืื ืคึฟืึทืจ ืืจืืขืื ืืื ืคืึทืจืฉืืื ืืึทืืึทืืืืกืื ืืืจื Nhibernate. ืืืจ ื ืืฆื ืื DB-First ืฆืืืึทื ื ื ืืฆื Liquibase, ืึทืืื ืขืก ืืื ืืืืื ืคืึทื ืืงืฉืึทื ืึทืืืื ืคึฟืึทืจ ืืจืืขืื ืืื ืืึทืื ืืื ืึท ืคืึทืจืืืง ืืึทืืึทืืืืก.
ViennaNET.Orm.Seedwork ะธ ViennaNET.Orm
- ืืืืคึผื ืึทืกืขืืืืื ืืื ืืงืขืจืืืง ืื ืืขืจืคืืืกืื ืืื ืืืืขืจ ืืืคึผืืึทืืึทื ืฅ ืจืืกืคึผืขืงืืืืืื. ืืื ืก ืงืืง ืืื ืืืืขืจ ืืื ืืึทืื ืืื ืืขืจ ืืขืืึทื.
ืฆืืืื ื IEntityFactoryService
ืืื ืืืึทื ืืืคึผืืึทืืขื ืืืืฉืึทื EntityFactoryService
ืืขื ืขื ืื ืืืืคึผื ืกืืึทืจืืื ื ืคืื ื ืคึฟืึทืจ ืืจืืขืื ืืื ืื ืืึทืืึทืืืืก, ืืื ื ืื ืึทืคึผืึทืจืึทื ืคืื ืึทืจืืขื, ืจืืคึผืึทืืึทืืึธืจืื ืคึฟืึทืจ ืืจืืขืื ืืื ืกืคึผืขืฆืืคืืฉ ืขื ืืืืื, ืืื ืืขืืื ื ืืื ืขืงืกืึทืงืืืืขืจื ืคืื ืงืึทืืึทื ืื ืืื ืืืจืขืงื ืกืงื ืงืืืืจืื ืืขื ืขื ืืืฉืืคื ืืึธ. ืืื ืขืก ืืื ืืึทืงืืืขื ืฆื ืืึทืืจืขื ืขืฆื ืื ืงืืืคึผืึทืืืืึทืืื ืคืื ืึท ืงืืึทืก ืคึฟืึทืจ ืืจืืขืื ืืื ืึท ืืึทืืึทืืืืก, ืืืฉื, ืฆื ืฆืืฉืืขืื ืื ืคืืืืงืืื ืืืืื ืฆื ืืืืขื ืขื ืืึทืื. ืคึฟืึทืจ ืึทืืึท ืงืึทืกืขืก IEntityFactoryService
ืขืก ืืื ืึทื ืึธืืืขืก - ืฆืืืื ื IEntityRepositoryFactory
, ืืืึธืก ืืืืื ืืขืจืงืืขืจื ืึท ืืขืืึธื ืคึฟืึทืจ ืงืจืืืืืื ื ืจืืคึผืึทืืึทืืึธืจืื.
ืฆื ืืืืื ืึทืงืกืขืก ืื ืืึทืืึทืืืืก, ืื ืฉืคึผืืึทืืขืจ ืืขืงืึทื ืืืึทื ืืื ืืขื ืืฆื. ืืขืืขืจ DBMS ืืืจ ื ืืฆื ืืื ืืื ืืืขืจ ืืืื ืืื ืืืื ืืืืืขื ืข ืืืคึผืืึทืืขื ืืืืฉืึทื: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql
.
ืืื ืืขืจ ืืขืืืืงืขืจ ืฆืืื, ืขืืืขืืข ืคึผืจืึทืืืืืืขืจื ืงืขื ืขื ืืืื ืจืขืืืกืืจืืจื ืืื ืืืื ืึทืคึผืืึทืงืืืฉืึทื ืืื ืืขืจ ืืขืืืืงืขืจ ืฆืืื, ืืืึธืก ืึทืืึทืื, ืืืฉื, ืืื ืื ืคืจืืืืืืขืจืง ืคืื ืืืื ืืื ืกื, ืึธื ืงืืื ืงืึธืก ืคึฟืึทืจ ืืึธืืืคืืฆืืจื ืื ืื ืคืจืึทืกืืจืึทืงืืฉืขืจ, ืฆื ืืืจืืคืืจื ืึท ืฉืจืื-ืคึฟืึทืจ-ืฉืจืื ืืืืจืึทืืืึธื ืคืื ืืืื ืขืจ DBMS ืฆื ืื ืืขืจื. ืืขืจ ืืขืงืึทื ืืืึทื ืคึฟืึทืจ ืกืึทืืขืงืืื ื ืื ืคืืจืืื ืื ืคึฟืึทืจืืื ืืื ื ืืื, ืืขืจืืืขืจ, ืืขืจ ืฉืคึผืืึทืืขืจ ืคึฟืึทืจ ืึท ืกืคึผืขืฆืืคืืฉ ืขื ืืืื ืงืืึทืก (ืคึฟืึทืจ ืืืึธืก ืืึทืคึผืื ื ืฆื ืืึทืืึทืืืืก ืืืฉื ืืื ืืขืฉืจืืื) ืืื ืืืคึผืืึทืืขื ืึทื ืืืจื ืจืขืืืฉืืกืืขืจืื ื ืื ืขื ืืืื ืืื ืื BoundedContext ืงืืึทืก (ืืื ืึท ืืขืืึธื ืคึฟืึทืจ ืจืขืืืฉืืกืืขืจืื ื ืคืขืื ืขื ืืืืื) ืึธืืขืจ ืืืื ืกืึทืงืกืขืกืขืจ ืึทืคึผืคึผืืืงืึทืืืึธื ืงืึธื ืืขืงืกื (ืืื ืืขืืืึธืืก ืคึฟืึทืจ ืจืขืืืฉืืกืืขืจืื ื ืึทืคึผืืึทืงืืืฉืึทื ืขื ืืืืื, ืืืจืขืงื ืจืืงืืืขืก ืืื ืงืึทืืึทื ืื), ืืื ืื ืงืึทื ืคืืืืขืจืืืฉืึทื ืืืืขื ืืืคึฟืืงืึทืฆืืข ืืื ืื ืืขื ืืืขื ืืื ืึทื ืึทืจืืืืขื ื:
"db": [
{
"nick": "mssql_connection",
"dbServerType": "MSSQL",
"ConnectionString": "...",
"useCallContext": true
},
{
"nick": "oracle_connection",
"dbServerType": "Oracle",
"ConnectionString": "..."
}
],
ืืืึทืฉืคึผืื ืึทืคึผืคึผืืืงืึทืืืึธื ืงืึธื ืืขืงืกื:
internal sealed class DbContext : ApplicationContext
{
public DbContext()
{
AddEntity<SomeEntity>("mssql_connection");
AddEntity<MigratedSomeEntity>("oracle_connection");
AddEntity<AnotherEntity>("oracle_connection");
}
}
ืืืื ืื ืคึฟืึทืจืืื ืืื ื ืฉืืึทื ืืื ื ืืฉื ืกืคึผืขืกืืคืืขื, ืืขืจ ืงืฉืจ ืืื ืื ื ืึธืืขื "ืคืขืืืงืืึทื" ืืืขื ืืืื ืืขืืืืื ื.
ืืืจืขืงื ืืึทืคึผืื ื ืคืื ืขื ืืืืื ืฆื ืืืืืึทืืืืก ืืืฉื ืืื ืืืคึผืืึทืืขื ืึทื ืืื ื ืึธืจืืึทื NHibernate ืืืฉืืจืื. ืืืจ ืงืขื ืขื ื ืืฆื ืื ืืึทืฉืจืืึทืืื ื ืืืืืข ืืืจื ืงืกืื ืืขืงืขืก ืืื ืืืจื ืงืืืกื. ืขืก ืืื ืึท ืืืืืืึธืืขืง ืคึฟืึทืจ ืืึทืงืืืขื ืฉืจืืืื ืคืื ืฉืืืื ืจืืคึผืึทืืึทืืึธืจืื ืืื ืืื ืื ืืขืกืฅ ViennaNET.TestUtils.Orm
.
ืืึทื ืฅ ืืืืฉืคืืื ืคืื ื ืืฆื ViennaNET.Orm.* ืงืขื ืขื ืืืื ืืขืคึฟืื ืขื
ViennaNET.Messaging.*
ื ืกืืื ืคืื ืืืืืจืขืจืื ืคึฟืึทืจ ืืจืืขืื ืืื ืงืืื.
ืฆื ืึทืจืืขืื ืืื ืจืืืขื, ืืขืจ ืืขืืืืงืขืจ ืฆืืืึทื ื ืืื ืืืืกืืขืจืืืืืื ืืื ืืื ืคืึทืจืฉืืื DBMS ืก, ื ืืืืื, ืื ืืึทืงืกืืืื ืืขืืืขื ืืื ืึทืคืืื ืฆืืืึทื ื ืืื ืืขืจืืื ืขื ืคืื ืืจืืขืื ืืื ืื ืืืืืืึธืืขืง, ืจืึทืืึทืจืืืึทืก ืคืื ืื ืจืื ืคืึทืจืืืึทืืืขืจ ืืขืืืืื ื. ืืืืืืึธืืขืง ViennaNET.Messaging
ืืื ืืขื ืื ืคืึทืจืึทื ืืืืึธืจืืืขื ืคึฟืึทืจ ืืขื ืืื ืึทืคืึทืงืืืฉืึทื, ืืื ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue ะธ ViennaNET.Messaging.KafkaQueue
ืึทื ืืืึทืืื ืึทืืึทืคึผืืขืจ ืืืคึผืืึทืืึทื ืฅ ืคึฟืึทืจ IBM MQ, RabbitMQ ืืื Kafka, ืจืืกืคึผืขืงืืืืืื.
ืืืขื ืืจืืขืื ืืื ืงืืื, ืขืก ืืขื ืขื ืฆืืืื ืคึผืจืึทืกืขืกืึทื: ืืึทืงืืืขื ืึท ืึธื ืืึธื ืืื ืฉืืงื ืขืก.
ืืึทืืจืึทืืื ืืืงืืืขื. ืืึธ ืืขื ืขื 2 ืึธืคึผืฆืืขืก: ืคึฟืึทืจ ืงืขืกืืืืขืจืืืง ืฆืืืขืืขืจื ืืื ืฆื ืืึทืงืืืขื ืึท ืืืื ืึธื ืืึธื. ืฆื ืงืขืกืืืืขืจ ืืขืจื ืฆื ืื ืจืื, ืืืจ ืืืื ืขืจืฉืืขืจ ืืึทืฉืจืืึทืื ืื ืคึผืจืึทืกืขืกืขืจ ืงืืึทืก ืื ืืขืจืึทืืื ืคืื IMessageProcessor
, ืืืึธืก ืืืขื ืืืื ืคืึทืจืึทื ืืืืึธืจืืืขื ืคึฟืึทืจ ืคึผืจืึทืกืขืกืื ื ืื ืื ืงืึทืืื ื ืึธื ืืึธื. ืืขืจื ืึธื, ืขืก ืืืื ืืืื "ืืื ืืงื" ืฆื ืึท ืกืคึผืขืฆืืคืืฉ ืจืื; ืืึธืก ืืื ืืืจืืืขืงืึธืื ืืืจื ืจืขืืืกืืจืึทืฆืืข ืืื IQueueReactorFactory
ืื ืืึทืงืืืืื ื ืื ืจืื ืืืืขื ืืืืขื ืคืื ืื ืงืึทื ืคืืืืขืจืืืฉืึทื:
"messaging": {
"ApplicationName": "MyApplication"
},
"rabbitmq": {
"queues": [
{
"id": "myQueue",
"queuename": "lalala",
...
}
]
},
ืืืึทืฉืคึผืื ืคืื ืึธื ืืืื ืฆืืืขืืขืจื:
_queueReactorFactory.Register<MyMessageProcessor>("myQueue");
var queueReactor = queueReactorFactory.CreateQueueReactor("myQueue");
queueReactor.StartProcessing();
ืืขืจื ืึธื, ืืืขื ืื ืืื ืกื ืกืืึทืจืฅ ืืื ืืขืจ ืืืคึฟื ืืื ืืขืจืืคึฟื ืฆื ืึธื ืืืืื ืฆืืืขืืขืจื, ืึทืืข ืึทืจืืืงืืขื ืคืื ืื ืกืคึผืขืกืึทืคืืื ืจืื ืืืขื ืืืื ืฆื ืื ืงืึธืจืึทืกืคึผืึทื ืืื ื ืคึผืจืึทืกืขืกืขืจ.
ืฆื ืืึทืงืืืขื ืึท ืืืื ืึธื ืืึธื ืืื ืึท ืคืึทืืจืืง ืฆืืืื ื IMessagingComponentFactory
ืขืก ืืื ืึท ืืืคึฟื CreateMessageReceiver
ืืืึธืก ืืืขื ืืึทืื ืึท ืืึทืงืืืขืจ ืืืืจืื ืคึฟืึทืจ ืึท ืึธื ืืึธื ืคืื ืืขืจ ืจืื ืกืคึผืขืกืืคืืขื ืฆื ืขืก:
using (var receiver = _messagingComponentFactory.CreateMessageReceiver<TestMessage>("myQueue"))
{
var message = receiver.Receive();
}
ืฆื ืฉืืงื ืึท ืึธื ืืึธื ืืืจ ืืึทืจืคึฟื ืฆื ื ืืฆื ืื ืืขืืืข IMessagingComponentFactory
ืืื ืฉืึทืคึฟื ืึท ืึธื ืืึธื ืกืขื ืืขืจ:
using (var sender = _messagingComponentFactory.CreateMessageSender<MyMessage>("myQueue"))
{
sender.SendMessage(new MyMessage { Value = ...});
}
ืขืก ืืขื ืขื ืืจืื ืืจืืื-ืืขืืืื ืึธืคึผืฆืืขืก ืคึฟืึทืจ ืกืืจืืึทืืืืื ื ืืื ืืขืกืขืจืืึทืืืืืื ื ืึท ืึธื ืืึธื: ื ืึธืจ ืืขืงืกื, XML ืืื JSON, ืึธืืขืจ ืืืื ื ืืืืืง, ืืืจ ืงืขื ืขื ืืืืื ืืึทืื ืืืื ืืืืืขื ืข ืฆืืืื ื ืืืคึผืืึทืืึทื ืฅ. IMessageSerializer ะธ IMessageDeserializer
.
ืืืจ ืืึธืื ืืขืคืจืืืื ืฆื ืืคืืืื ืื ืืื ืฆืืง ืงืืืคึผืึทืืืืึทืืื ืคืื ืืขืืขืจ ืจืื ืคืึทืจืืืึทืืืขืจ, ืืืฉื. ViennaNET.Messaging.MQSeriesQueue
ืึทืืึทืื ืืืจ ืฆื ืฉืืงื ื ืื ืืืืื ืืขืงืกื, ืึธืืขืจ ืืืื ืืืื ืึทืจืืืงืืขื, ืืื ViennaNET.Messaging.RabbitMQQueue
ืฉืืืฆื ืจืืืื ื ืืื ืืืืฃ-ืืขื-ืคืืืขื ืจืื. ืืื ืืืขืจ ืึทืืึทืคึผืืขืจ ืจืึทืคึผืขืจ ืคึฟืึทืจ RabbitMQ ืืืื ืืืคึผืืึทืืึทื ืฅ ืขืืืขืืข ืกืืืืึทืืึทื ืก ืคืื RPC: ืืืจ ืฉืืงื ืึท ืึธื ืืึธื ืืื ืืืึทืจืื ืคึฟืึทืจ ืึท ืขื ืืคืขืจ ืคืื ืึท ืกืคึผืขืฆืืขื ืฆืืึทืืืืืึทืืืง ืจืื, ืืืึธืก ืืื ืืืฉืืคื ืืืืื ืคึฟืึทืจ ืืืื ืขื ืืคืขืจ ืึธื ืืึธื.
ืืึธ
ViennaNET.CallContext
ืืืจ ื ืืฆื ืงืืื ื ืื ืืืืื ืคึฟืึทืจ ืื ืืึทืืจืืืฉืึทื ืฆืืืืฉื ืคืึทืจืฉืืืขื ืข ืกืืกืืขืืขื, ืึธืืขืจ ืืืื ืคึฟืึทืจ ืงืึธืืื ืืงืึทืฆืืข ืฆืืืืฉื ืืืงืจืึธ ืืึทืืื ืื ืืก ืคืื ืืขืจ ืืขืืืืงืขืจ ืึทืคึผืืึทืงืืืฉืึทื, ืคึฟืึทืจ ืืืึทืฉืคึผืื, ืืื ืึท ืกืึทืืข. ืืึธืก ืืึธื ืืขืคึฟืืจื ืฆื ืื ื ืืืืืง ืฆื ืืืขืจืฉืืงื ืืื ืืขื ืึธื ืืึธื ืึทืืึท ืึทืืืืืืขืจื ืืึทืื ืืื ืืขืจ ืืึทื ืืฆืขืจ ืืึธืืื, ืืขืื ืืืืขื ืืืคืืฆืืจื ืคึฟืึทืจ ืกืืฃ-ืฆื-ืกืืฃ ืืึธืืื ื, ืืงืืจ IP ืึทืืจืขืก ืืื ืืขืจืืืืืขื ืืฉ ืืึทืื. ืฆื ืื ืกืืจืืืขื ื ืื ืคืึธืจืืืขืจืืื ื ืคืื ืื ืืึทืื, ืืืจ ืืขืืืขืืึธืคึผืขื ืึท ืืืืืืึธืืขืง ViennaNET.CallContext
, ืืืึธืก ืึทืืึทืื ืืืจ ืฆื ืงืจืึธื ืืึทืื ืคึฟืื ืึท ืืงืฉื ืืืึธืก ืงืืื ืืื ืื ืืื ืกื. ืืื ืืขื ืคืึทื, ืื ืืืขื ืื ืืขืื ืืื ืืขืืืื, ืืืจื ืึท ืจืื ืึธืืขืจ ืืืจื ืืืืคึผ, ืืื ื ืืฉื ืขื ืื. ืืขืจื ืึธื, ืืืืืขืจ ืืืจ ืฉืืงื ืื ืึทืืืืึธืืื ื ืืขืื ืึธืืขืจ ืึธื ืืึธื, ืืึทืื ืืขื ืขื ืืขื ืืืขื ืคืื ืืขื ืงืึธื ืืขืงืกื ืืื ืืขืฉืืขืื ืืื ืื ืืขืืขืจื. ืืืื, ืืขืจ ืืืืึทืืขืจ ืืื ืกื ื ืขืื ืื ืึทืืืืืืขืจื ืืึทืื ืืื ืืึทื ืืืืฉืื ืขืก ืืื ืื ืืขืืืข ืืืขื.
ืืื ืง ืืืจ ืคึฟืึทืจ ืืืื ืืคืืขืจืงืืึทืืงืืื, ืืืจ ืงืืงื ืคืึธืจืืืก ืฆื ืืืื ืืึทืืขืจืงืื ืืขื ืืื ืฆืืขื ืจืืงืืืขืก!
ืืงืืจ: www.habr.com