রাষ্ট্রীয় অবজেক্টগুলি নির্মাণের ক্ষেত্রে কোনও প্রভাবের ধরণের মডেল করা উচিত?


9

স্কালার মতো একটি কার্যকরী পরিবেশ ব্যবহার করার সময় এবং cats-effectরাষ্ট্রীয় সামগ্রীর নির্মাণকে কোনও প্রভাবের ধরণের সাহায্যে মডেল করা উচিত?

// not a value/case class
class Service(s: name)

def withoutEffect(name: String): Service =
  new Service(name)

def withEffect[F: Sync](name: String): F[Service] =
  F.delay {
    new Service(name)
  }

নির্মাণটি হ্রাসযোগ্য নয়, সুতরাং আমরা দুর্বল টাইপক্লাসের মতো ব্যবহার করতে পারি Apply

// never throws
def withWeakEffect[F: Applicative](name: String): F[Service] =
  new Service(name).pure[F]

আমি অনুমান করি যে এগুলি সবই খাঁটি এবং নির্দোষ। ফলস্বরূপ উদাহরণটি প্রতিটি সময় পৃথক হওয়ার কারণে কেবল উল্লেখযোগ্যভাবে স্বচ্ছ নয়। এফেক্ট-টাইপ ব্যবহার করার জন্য কি এটি ভাল সময়? বা এখানে কি আলাদা কার্যকরী প্যাটার্ন থাকবে?


2
হ্যাঁ, পরিবর্তনীয় রাষ্ট্রের সৃষ্টি একটি পার্শ্ব-প্রতিক্রিয়া। এর মতো, এটি একটি এর অভ্যন্তরে ঘটতে হবে delayএবং একটি এফ [পরিষেবা] ফিরিয়ে দেওয়া উচিত । উদাহরণ হিসাবে, আইও-start তে পদ্ধতিটি দেখুন , এটি প্লেইন ফাইবারের পরিবর্তে একটি আইও [ফাইবার [আইও,?]] প্রদান করে ।
লুইস মিগুয়েল মেজিয়া সুরেজ

1
এই সমস্যার সম্পূর্ণ উত্তরের জন্য দয়া করে এটি এবং এটি দেখুন
লুইস মিগুয়েল মেজিয়া সুরেজ

উত্তর:


3

রাষ্ট্রীয় অবজেক্টগুলি নির্মাণের ক্ষেত্রে কোনও প্রভাবের ধরণের মডেল করা উচিত?

আপনি যদি ইতিমধ্যে একটি প্রভাব ব্যবস্থা ব্যবহার করে থাকেন তবে সম্ভবত এটির পরিবর্তিত Refস্থিতিস্থাপকতার জন্য নিরাপদে একটি প্রকার রয়েছে ।

তাই আমি বলি: মডেল রাষ্ট্রীয় বস্তুগুলির সাথেRef । যেহেতু এগুলি তৈরির (পাশাপাশি অ্যাক্সেসের) ইতিমধ্যে একটি প্রভাব রয়েছে, এটি স্বয়ংক্রিয়ভাবে পরিষেবাটি তৈরি করাও কার্যকর করে তুলবে।

এটি আপনার আসল প্রশ্নটি ঝরঝরে করে।

আপনি যদি নিয়মিতভাবে ম্যানুয়ালি অভ্যন্তরীণ পরিবর্তনীয় স্থিতি পরিচালনা করতে চান তবে আপনাকে varনিজের দ্বারা নিশ্চিত করতে হবে যে এই রাজ্যে স্পর্শ করা সমস্ত অপারেশনগুলি প্রভাব হিসাবে বিবেচিত হয় (এবং সম্ভবত এটি থ্রেড-নিরাপদও হয়ে থাকে), যা ক্লান্তিকর এবং ত্রুটি-প্রবণ। এটি করা যেতে পারে, এবং আমি @ অটলের এই জবাবের সাথে একমত যে আপনাকে রাষ্ট্রীয় অবজেক্টের সৃষ্টি কার্যকরভাবে কার্যকর করতে হবে না (যতক্ষণ না আপনি রেফারেন্সিয়াল অখণ্ডতার ক্ষতিতে বাঁচতে পারবেন) তবে কেন নিজেকে বাঁচাতে এবং আলিঙ্গন করবেন না? আপনার প্রভাব সিস্টেমের সরঞ্জামগুলি কি পুরোপুরি?


আমি অনুমান করি যে এগুলি সবই খাঁটি এবং নির্বিচারবাদী। ফলস্বরূপ উদাহরণটি প্রতিটি সময় পৃথক হওয়ার কারণে কেবল উল্লেখযোগ্যভাবে স্বচ্ছ নয়। এফেক্ট-টাইপ ব্যবহার করার জন্য কি এটি ভাল সময়?

আপনার প্রশ্নটি যদি পুনরায় করা যায় তবে

রেফারেন্সিয়াল স্বচ্ছতা এবং "স্থানীয়ভাবে যুক্তি যুক্তিযুক্ত প্রভাব (যেমন ইতিমধ্যে রাষ্ট্রের অ্যাক্সেস এবং মিউটেশনের জন্য ইতিমধ্যে ব্যবহারে থাকতে হবে) ব্যবহারের পক্ষে যুক্তিযুক্ত করার পক্ষে অতিরিক্ত সুবিধা ((" দুর্বল টাইপক্লাস "ব্যবহার করে একটি সঠিকভাবে কার্যকর বাস্তবায়নের শীর্ষে)) কি রাষ্ট্রের জন্য? সৃষ্টি?

তারপরে: হ্যাঁ, একেবারে

কেন এটি কার্যকর তা উদাহরণ দেওয়ার জন্য:

নিম্নলিখিতটি কার্যকর কাজ করে, যদিও পরিষেবা তৈরি কার্যকরভাবে কার্যকর হয় নি:

val service = makeService(name)
for {
  _ <- service.doX()
  _ <- service.doY()
} yield Ack.Done

তবে আপনি যদি নীচের হিসাবে এটি রিফ্যাক্টর করে থাকেন তবে আপনি একটি সংকলন-সময় ত্রুটি পাবেন না, তবে আপনি আচরণটি পরিবর্তন করতে পারবেন এবং সম্ভবত একটি বাগটি প্রবর্তন করেছেন। আপনি যদি কার্যকর হিসাবে ঘোষণা makeServiceকরেছিলেন, রিফ্যাক্টরিং টাইপ-চেক করবে না এবং সংকলক দ্বারা প্রত্যাখাত হবে।

for {
  _ <- makeService(name).doX()
  _ <- makeService(name).doY()
} yield Ack.Done

পদ্ধতিটির নামকরণ হিসাবে makeService(এবং একটি প্যারামিটার সহ) নামকরণের বিষয়টি পদ্ধতিটি কী পরিষ্কার করে তোলে তা পরিষ্কার করে দেওয়া উচিত এবং এটি যে রিফেক্টরিং করা কোনও নিরাপদ জিনিস ছিল না, তবে "স্থানীয় যুক্তি" এর অর্থ হল আপনার তাকাতে হবে না নামকরণের সম্মেলন এবং এটি নির্ধারণের বাস্তবায়নে makeService: যেকোন মত প্রকাশ যা যান্ত্রিকভাবে চারপাশে বদলানো যায় না (অনুলিপি করা, অলসভাবে তৈরি করা, উত্সাহী, ডেড-কোড নির্মূল, সমান্তরাল, বিলম্বিত, ক্যাশে করা, ক্যাশে থেকে শুকানো ইত্যাদি) আচরণ পরিবর্তন না করে ( যেমন "খাঁটি" নয়) কার্যকর হিসাবে টাইপ করা উচিত।


2

রাষ্ট্রীয় পরিষেবা এই ক্ষেত্রে কী বোঝায়?

আপনি কী বোঝাতে চাইছেন যে কোনও বস্তুটি নির্মিত হলে এটি কোনও পার্শ্ব প্রতিক্রিয়াটি কার্যকর করবে? এর জন্য, আরও ভাল ধারণা হ'ল আপনার অ্যাপ্লিকেশন শুরু হওয়ার সাথে সাথে এমন কোনও পদ্ধতি থাকা যা পার্শ্ব প্রতিক্রিয়াটি চালায়। পরিবর্তে এটি নির্মাণের সময় চালানো।

অথবা হতে পারে আপনি বলছেন যে এটি পরিষেবার অভ্যন্তরে একটি পরিবর্তনীয় অবস্থা ধরে রেখেছে? যতক্ষণ না অভ্যন্তরীণ পরিবর্তনযোগ্য অবস্থা প্রকাশিত হয় না ততক্ষণ এটি ঠিক হয়ে যাওয়া উচিত। পরিষেবার সাথে যোগাযোগের জন্য আপনাকে কেবল একটি খাঁটি (সাধারণভাবে স্বচ্ছ) পদ্ধতি সরবরাহ করতে হবে।

আমার দ্বিতীয় পয়েন্টটি প্রসারিত করতে:

ধরা যাক আমরা একটি মেমরি ডিবি নির্মাণ করছি।

class InMemoryDB(private val hashMap: ConcurrentHashMap[String, String]) {
  def getId(s: String): IO[String] = ???
  def setId(s: String): IO[Unit] = ???
}

object InMemoryDB {
  def apply(hashMap: ConcurrentHashMap[String, String]) = new InMemoryDB(hashMap)
}

আইএমও, এটি কার্যকর হওয়ার দরকার নেই, আপনি যদি নেটওয়ার্ক কল করেন তবে একই জিনিসটি ঘটছে। যদিও, আপনাকে অবশ্যই নিশ্চিত করতে হবে যে এই শ্রেণীর একমাত্র উদাহরণ রয়েছে।

আপনি যদি Refবিড়াল-প্রভাব থেকে ব্যবহার করছেন , তবে আমি সাধারণত যা করতাম তা flatMapএন্ট্রি পয়েন্টের রেফের কাছে হয়, যাতে আপনার শ্রেণি কার্যকর হয় না।

object Effectful extends IOApp {

  class InMemoryDB(storage: Ref[IO, Map[String, String]]) {
    def getId(s: String): IO[String] = ???
    def setId(s: String): IO[Unit] = ???
  }

  override def run(args: List[String]): IO[ExitCode] = {
    for {
      storage <- Ref.of[IO, Map[String, String]](Map.empty[String, String])
      _ = app(storage)
    } yield ExitCode.Success
  }

  def app(storage: Ref[IO, Map[String, String]]): InMemoryDB = {
    new InMemoryDB(storage)
  }
}

ওটিওহ, আপনি যদি কোনও শেয়ার্ড সার্ভিস বা একটি লাইব্রেরি লিখছেন যা রাষ্ট্রীয় অবজেক্টের উপর নির্ভরশীল (একাধিক সম্মতিমূলক আদিমন্ত্রীরা বলি) এবং আপনি চান না যে আপনার ব্যবহারকারীরা কী শুরু করতে হবে সেদিকে খেয়াল রাখুক।

তারপরে, হ্যাঁ, এটি একটি প্রভাব আবৃত করা আবশ্যক। আপনি Resource[F, MyStatefulService]সবকিছু ঠিকঠাকভাবে বন্ধ আছে কিনা তা নিশ্চিত করতে আপনি এর মতো কিছু ব্যবহার করতে পারেন । বা F[MyStatefulService]বন্ধ করার মতো কিছুই যদি না থাকে।


"আপনাকে কেবল পরিষেবার সাথে যোগাযোগের জন্য একটি পদ্ধতি একটি বিশুদ্ধ পদ্ধতি সরবরাহ করতে হবে" বা সম্ভবত এর বিপরীত: খাঁটি অভ্যন্তরীণ রাষ্ট্রের প্রাথমিক নির্মাণের কোনও প্রভাব হওয়ার দরকার নেই, তবে সেই পরিবর্তনের অবস্থার সাথে যোগাযোগ করে এমন পরিষেবাতে কোনও অপারেশন operation যে কোনও উপায়ে তারপরে কার্যকর হিসাবে চিহ্নিত করা দরকার (যেমন দুর্ঘটনা এড়াতে val neverRunningThisButStillMessingUpState = Task.pure(service.changeStateThinkingThisIsPure()).repeat(5))
থিলো

বা অন্য দিক থেকে আসছে: আপনি যদি পরিষেবাটি কার্যকর তৈরি করেন বা না করেন তবে তা গুরুত্বপূর্ণ নয়। তবে আপনি যে পথেই যান না কেন, সেবার সাথে কোনওভাবেই ইন্টারঅ্যাক্ট করা অবশ্যই কার্যকর হতে হবে (কারণ এটি অভ্যন্তরে পরিবর্তনীয় অবস্থা বহন করে যা এই ইন্টারঅ্যাকশনগুলির দ্বারা প্রভাবিত হবে)।
থিলো

1
হ্যাঁ, আপনি ঠিক বলেছেন আমি যা বোঝাতে চেয়েছি pureতা হ'ল এটি অবশ্যই স্বচ্ছ হতে হবে। যেমন ফিউচারের সাথে একটি উদাহরণ বিবেচনা করুন। val x = Future {... }এবং def x = Future { ... }একটি ভিন্ন জিনিস মানে। (আপনি যখন নিজের কোডটি রিফ্যাক্ট করছেন তখন এটি আপনাকে কামড় দিতে পারে) তবে, বিড়াল-প্রভাব, মনিক্স বা জাইওর ক্ষেত্রে তা নয়।
atl
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.