পাইথন "গড ক্লাস" কীভাবে রিফ্যাক্টর করবেন?


10

সমস্যা

আমি পাইথন প্রকল্পে কাজ করছি যার মূল শ্রেণিটি কিছুটা " গড অবজেক্ট "। আছে তাই friggin 'অনেকগুলো চারিত্রিক বৈশিষ্ট্য ও পদ্ধতি!

আমি ক্লাস রিফ্যাক্টর করতে চাই।

যতদূর…

প্রথম পদক্ষেপের জন্য, আমি তুলনামূলক সহজ কিছু করতে চাই; তবে যখন আমি সবচেয়ে সহজ পদ্ধতির চেষ্টা করেছি তখন এটি কিছু পরীক্ষা এবং বিদ্যমান উদাহরণগুলিকে ভেঙে দিয়েছে।

মূলত, শ্রেণীর গুণাবলীর একটি দীর্ঘ তালিকা রয়েছে — তবে আমি তাদের পরিষ্কারভাবে দেখতে পারি এবং ভাবতে পারি, "এই 5 টি বৈশিষ্ট্য সম্পর্কিত related এই 8 টিও সম্পর্কিত… এবং এরপরেও বাকি রয়েছে” "

getattr

আমি মূলত কেবলমাত্র সম্পর্কিত বৈশিষ্ট্যগুলিকে একটি ডিকের মতো সহায়ক শ্রেণিতে গ্রুপ করতে চেয়েছিলাম। আমি একটি অনুভূতি ছিল __getattr__কাজের জন্য আদর্শ হতে হবে। সুতরাং আমি বৈশিষ্ট্যগুলিকে একটি পৃথক শ্রেণিতে স্থানান্তরিত করেছি এবং নিশ্চিতভাবেই, __getattr__এর যাদুটি পুরোপুরি ভালভাবে কাজ করেছে ...

প্রথম

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

@property

আমি তখন @propertyশোভাকর সম্পর্কে পড়েছি । তবে আমি আরও পড়লাম যে এটি সাবক্লাসগুলির জন্য সমস্যা তৈরি করে যা self.x = blahযখন xপিতৃত শ্রেণীর সম্পত্তি হয় তখন করতে চায় ।

আকাঙ্ক্ষিত

  • সমস্ত ক্লায়েন্ট কোড ব্যবহার করে কাজ চালিয়ে যান self.whatever, এমনকি পিতামাতার whateverসম্পত্তি ক্লাসে (বা উদাহরণ) নিজেই "শারীরিকভাবে অবস্থিত" না থাকলেও।
  • গোষ্ঠী সম্পর্কিত গুণাবলী ডিকের মতো পাত্রে ভাগ করুন।
  • মূল শ্রেণিতে কোডের চরম কোলাহলকে হ্রাস করুন।

উদাহরণস্বরূপ, আমি কেবল এটি পরিবর্তন করতে চাই না :

larry = 2
curly = 'abcd'
moe   = self.doh()

এটিতে:

larry = something_else('larry')
curly = something_else('curly')
moe   = yet_another_thing.moe()

… কারণ এখনও শোরগোল। যদিও এটি সাফল্যের সাথে এমন কিছুতে একটি সহজ বৈশিষ্ট্য তৈরি করে যা ডেটা পরিচালনা করতে পারে, মূলটিতে 3 টি ভেরিয়েবল ছিল এবং টুইড সংস্করণে এখনও 3 ভেরিয়েবল রয়েছে।

যাইহোক, আমি এই জাতীয় কিছু সঙ্গে ভাল হবে:

stooges = Stooges()

এবং যদি কোনও self.larryব্যর্থতার জন্য অনুসন্ধান ব্যর্থ হয় তবে কিছু পরীক্ষা করে stoogesদেখতে হবে larryযে সেখানে আছে কিনা । (তবে একটি সাবক্লাস larry = 'blah'ক্লাস পর্যায়ে করার চেষ্টা করলে এটি অবশ্যই কার্যকর হবে ))

সারসংক্ষেপ

  • প্যারেন্ট ক্লাসে বৈশিষ্ট্যের সম্পর্কিত গোষ্ঠীগুলিকে একক অ্যাট্রিবিউটের সাথে প্রতিস্থাপন করতে চান যা সমস্ত ডেটা অন্য কোথাও সঞ্চয় করে
  • larry = 'blah'ক্লাস স্তরে (যেমন) ব্যবহার করে এমন ক্লায়েন্ট কোডগুলির সাথে কাজ করতে চান
  • সাব-ক্লাসগুলি কিছু না জেনেও এই রিফ্যাক্টরযুক্ত বৈশিষ্ট্যগুলি প্রসারিত, ওভাররাইড এবং সংশোধন করার অনুমতি অবিরত রাখতে চান


এটা কি সম্ভব? নাকি আমি ভুল গাছটি ছাঁটাই করছি?


6
আপনি বাস্তবায়নের অংশগুলি পৃথক করেও, যদি আপনি এখনও এই বিশাল godশ্বরের মতো ইন্টারফেস রাখার জন্য জোর দিয়ে থাকেন তবে তার অর্ধেক সুবিধা হারাচ্ছেন। আপনি শর্টকাট সরবরাহ করতে পারেন, তবে কেবল বিভিন্ন নামের জায়গাগুলিতে ভেরিয়েবলগুলি রেখে এবং সেগুলিতে সম্পূর্ণরূপে পুনর্নির্দেশ করা যদি আপনাকে কিছু দেয় তবে খুব কম দেয়।

1
@ ডেলানন: ঠিক আছে, তবে এর পরিবর্তে আপনি কি সুপারিশ করবেন?
জেরেইন

উত্তর:


9

অজগর "গড অবজেক্ট" লিখে এবং তারপরে রিফেক্টর করে আমি সহানুভূতি জানাই। আমি যা করেছি তা হ'ল মূল অবজেক্টটি পদ্ধতিগুলির উপর ভিত্তি করে সাব বিভাগে বিভক্ত করা। উদাহরণস্বরূপ, আসলটি এই ছদ্ম কোডের মতো দেখাচ্ছে:

method A():
    self.bla += 1

method B():
    self.bla += 1

do stuff():
    self.bla = 1
    method A()
    method B()
    print self.bla

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

"গড অবজেক্ট" ভাগ করা শ্রেণীর শুরুতে নতুন কপি তৈরি করে এবং নতুন উপ শ্রেণীর প্রত্যেকটি তাদের আর ডি পদ্ধতির অংশ হিসাবে একটি পয়েন্টার গ্রহণ করে। উদাহরণস্বরূপ, এখানে মেলারের একটি ছিটিয়ে থাকা সংস্করণ:

#!/usr/bin/env python
# -*- coding: ascii -*-
'''Functions for emailing with dirMon.'''

from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os
import smtplib
import datetime
import logging

class mailer:
    def __init__(self,SERVER="mail.server.com",FROM="support@server.com"):
        self.server = SERVER
        self.send_from = FROM
        self.logger = logging.getLogger('dirMon.mailer')

    def send_mail(self, send_to, subject, text, files=[]):
        assert type(send_to)==list
        assert type(files)==list
        if self.logger.isEnabledFor(logging.DEBUG):
            self.logger.debug(' '.join(("Sending email to:",' '.join(send_to))))
            self.logger.debug(' '.join(("Subject:",subject)))
            self.logger.debug(' '.join(("Text:",text)))
            self.logger.debug(' '.join(("Files:",' '.join(files))))
        msg = MIMEMultipart()
        msg['From'] = self.send_from
        msg['To'] = COMMASPACE.join(send_to)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
        msg.attach( MIMEText(text) )
        for f in files:
            part = MIMEBase('application', "octet-stream")
            part.set_payload( open(f,"rb").read() )
            Encoders.encode_base64(part)
            part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
            msg.attach(part)
        smtp = smtplib.SMTP(self.server)
        mydict = smtp.sendmail(self.send_from, send_to, msg.as_string())
        if self.logger.isEnabledFor(logging.DEBUG):
            self.logger.debug("Email Successfully Sent!")
        smtp.close()
        return mydict

এটি একবার তৈরি এবং বিভিন্ন ক্লাসের মধ্যে ভাগ করা হয় যা মেলিংয়ের ক্ষমতা প্রয়োজন।

সুতরাং আপনার জন্য, larryআপনার প্রয়োজনীয় বৈশিষ্ট্য এবং পদ্ধতিগুলি সহ একটি শ্রেণি তৈরি করুন । ক্লায়েন্ট যেখানেই বলছে larry = blahএটির সাথে প্রতিস্থাপন করুন larryObj.larry = blah। এটি বর্তমান ইন্টারফেসটি না ভেঙে সাব-প্রোজেক্টগুলিতে জিনিসগুলি স্থানান্তর করে।

"কাজের একক" অনুসন্ধান করা ছাড়া অন্য একমাত্র কাজ। আপনি "ঈশ্বর অবজেক্ট" এটা নিজস্ব পদ্ধতি মধ্যে অংশ ঘুরে যাচ্ছিল পারেন, তাই । তবে, পদ্ধতিটি এর বাইরে রাখুন। এটি আপনাকে উপাদানগুলির মধ্যে একটি ইন্টারফেস তৈরি করতে বাধ্য করে।

সেই ভিত্তি স্থাপনের ফলে অন্য সমস্ত কিছু এটি অনুসরণ করতে দেয়। উদাহরণস্বরূপ, সহায়িকার বস্তুর এক টুকরো এটি দেখায় যে এটি মেলারের সাথে কীভাবে ইন্টারফেস করে:

#!/usr/bin/env python
'''This module holds a class to spawn various subprocesses'''
import logging, os, subprocess, time, dateAdditionLib, datetime, re

class spawner:
    def __init__(self, mailer):
        self.logger = logging.getLogger('dirMon.spawner')
        self.myMailer = mailer

কাজের ক্ষুদ্রতম পৃথক ইউনিটকে মনোনিবেশ করুন এবং এটিকে সরিয়ে দিন। এটি করা সহজ, এবং আপনাকে দ্রুত সেটআপ দিয়ে খেলতে দেয়। স্টাফ স্থানান্তরিত করার জন্য বৈশিষ্ট্যগুলির দিকে তাকান না, তারা বেশিরভাগ ক্ষেত্রে তাদের সাথে যে কাজগুলি করা হচ্ছে তার সাথে আনুষঙ্গিক । আপনি পদ্ধতিগুলি মোকাবেলা করার পরে যা কিছু অবশিষ্ট রয়েছে তা সম্ভবত আসল বস্তুতে থাকা উচিত , কারণ এটি ভাগ করা রাষ্ট্রের অংশ state

তবে , নতুন বস্তুগুলির এখন আর ডি ভেরিয়েবল হিসাবে তাদের প্রয়োজনীয় বৈশিষ্ট্যগুলি গ্রহণ করা উচিত, কলার অবজেক্টের সম্পত্তিটির স্পর্শ না করে। এরপরে তারা কোনও প্রয়োজনীয় মানগুলি ফেরত দেয়, যা কলকারী প্রয়োজনীয় হিসাবে ভাগ করা বৈশিষ্ট্যগুলি আপডেট করতে ব্যবহার করতে পারে। এটি বস্তুগুলি ডিকুয়াল করতে সহায়তা করে এবং আরও শক্তিশালী সিস্টেম তৈরি করে।


1
চমত্কার উত্তর, স্পেন্সার। ধন্যবাদ! আমার কিছু ফলো-আপ প্রশ্ন রয়েছে যা প্রকৃতির পক্ষে খুব নির্দিষ্ট এটি উপযুক্ত be এগুলি আলোচনা করার জন্য আমি কি আপনার সাথে ব্যক্তিগতভাবে যোগাযোগ করতে পারি?
জেরিন

@ জয়ার নিশ্চিত, আমার প্রোফাইলে আমার ইমেল ঠিকানা রয়েছে। এটি যদিও কোনও সংস্থা প্রকল্পের জন্য ছিল এবং সেখানে মালিকানাধীন জিনিসগুলির কারণে আমি আপনাকে সংগ্রহস্থলের একটি সম্পূর্ণ অনুলিপি দিতে পারি না। পর্যাপ্ত পরিমাণ দেওয়া, আমি স্ন্যাপশটের আগে / পরে পরিষ্কার করতে পারতাম, তবে আমি নিশ্চিত নই যে এটি আপনাকে কতটা সহায়তা করবে।
স্পেনসার রথবুন

আমি আপনার প্রোফাইলে কোনও ইমেল ঠিকানা দেখতে পাচ্ছি না। এখানে সমস্ত ধরণের তথ্য রয়েছে তবে যোগাযোগের তথ্য নেই। I আমি কিভাবে আপনার সাথে যোগাযোগ করব?
জেরেইন

বুঝেছি. সাইবারম্যান: “মুছুন! মুছে ফেলা! মুছে ফেলা!"
জেরেইন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.