Какое соглашение о присвоении имен Вы используете для уровня служб в Spring приложение MVC? [закрытый]

Я случайно увидел это на боковой панели, у меня недавно была такая же проблема. К сожалению, из-за ограничений времени выполнения Objective C вы не можете использовать @objc для расширений протокола, я думаю, что эта проблема была закрыта в начале этого года.

Проблема возникает из-за того, что расширение добавляется после соответствия протокола, поэтому нет способа гарантировать, что соответствие протоколу будет выполнено. Тем не менее, можно вызывать метод как селектор из всего, что подклассов NSObject и соответствует протоколу. Чаще всего это делается с делегированием.

Это означает, что вы можете создать пустой подкласс обертки, соответствующий протоколу, и использовать обертку для вызова его методов из протокола, определенного в обертке, любые другие неопределенные методы из протокола могут быть переданы в делегировать. Существуют другие аналогичные решения, которые используют частное расширение конкретного класса, например UIViewController, и определяют метод, который вызывает метод протокола, но они также связаны с конкретным классом, а не реализацией по умолчанию конкретного класса, который происходит с соответствуют протоколу .

Поймите, что вы пытаетесь реализовать реализацию протокола по умолчанию, которая использует другую из своих собственных функций протокола, чтобы определить значение для своей собственной реализации. гмм!

Протокол:

 public protocol CustomViewDelegate {
     func update()
     func nonDelegatedMethod()
}

Представление:

Использование делегата и определение метода обертки для безопасного развертывания метод делегата.

class CustomView: UIView {

    let updateButton: UIButton = {
        let button = UIButton(frame: CGRect(origin: CGPoint(x: 50, y: 50), size: CGSize(width: 150, height: 50)))
        button.backgroundColor = UIColor.lightGray
        button.addTarget(self, action: #selector(doDelegateMethod), for: .touchUpInside)
        return button
    }()

    var delegate:CustomViewDelegate?

    required init?(coder aDecoder: NSCoder) {
        fatalError("Pew pew, Aghh!")
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(updateButton)
    }

    @objc func doDelegateMethod() {
        if delegate != nil {
           delegate!.update()
        } else {
           print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
        }
     }


   }

ViewController:

Согласуйте контроллер представления с представителем представления: и реализуйте метод протокола.

class ViewController: UIViewController, CustomViewDelegate {

    let customView = CustomView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))

    override func viewDidLoad() {
        super.viewDidLoad()
        customView.backgroundColor = UIColor.red
        customView.delegate = self //if delegate is not set, the app will not crash
        self.view.addSubview(customView)
    }

    // Protocol -> UIView Button Action -> View Controller's Method
    func update() {
        print("Delegating work from View that Conforms to CustomViewDelegate to View Controller")
    }

    //Protocol > View Controller's Required Implementation
    func nonDelegatedMethod() {

       //Do something else 

   }
}

Обратите внимание, что контроллер представления должен был соответствовать только делегату и не устанавливал селектор какого-либо свойства представления, это отделяет представление (и его протокол) от контроллера представления.

У вас уже есть UIView с именем TapView, который наследует от UIView и Tappable, поэтому ваша реализация может быть:

Протокол:

protocol TappableViewDelegate {
    func tapGestureDetected(gesture:UITapGestureRecognizer)
}

TappableView:

class TappableView: UIView {

    var delegate:TappableViewDelegate?

    required init?(coder aDecoder: NSCoder) {
        fatalError("Pew pew, Aghh!")
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        let gesture = UITapGestureRecognizer(target: self, action: #selector(doDelegateMethod(gesture:)))
        addGestureRecognizer(gesture)
    }

    @objc func doDelegateMethod(gesture:UITapGestureRecognizer) {
        if delegate != nil {
            delegate!.tapGestureDetected(gesture: gesture)
        } else {
            print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
        }
    }

}

ViewController:

class ViewController: UIViewController, TappableViewDelegate {

    let tapView = TappableView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))

    override func viewDidLoad() {
        super.viewDidLoad()
        tapView.backgroundColor = UIColor.red
        tapView.delegate = self
        self.view.addSubview(tapView)
    }

    func tapGestureDetected(gesture: UITapGestureRecognizer) {
        print("User did tap")
   }

}
42
задан Vasil 15 June 2009 в 10:49
поделиться

5 ответов

Spring сам дает интерфейсам общие имена, а затем имена классов на основе деталей реализации. Это один из примеров, который приходит на ум:

interface: Controller
abstract classes: AbstractController, AbstractCommandController, 
                  SimpleFormController, MultiActionController

Я не думаю, что такие имена, как SimpleUserAccountManager или UserAccountDbManager, являются глупыми, поскольку они передают некоторую информацию о реализации менеджера / службы.

Я считаю глупым обычное соглашение чтобы добавить суффикс «Impl» в классы реализации:

my/package/UserAccountManager
my/package/impl/UserAccountManagerImpl

Некоторые люди предпочитают это.

18
ответ дан 26 November 2019 в 23:35
поделиться

Я считаю, что суффикс именования службы vs. Manager является чисто предпочтительным. Единственный случай, когда «Сервис» когда-либо нас смущал, - это когда у нас также есть веб-сервисы, расположенные на вершине нашего сервисного уровня. В некоторых проектах мы просто называли классы веб-сервисов посредниками, поскольку все, что они делали, это служили для преобразования или посредничества вызова веб-сервиса в вызовы нашего уровня сервиса.

Я согласен с kgiannakakis, который добавлял к вашим реализациям суффикс «Impl "не лучший подход. Я также сталкивался с лучшими практиками кодирования, в которых упоминается, что этого нельзя делать. Называть интерфейс после абстракции - это общепринятая передовая практика. Называя класс реализации после интерфейса с некоторым индикатором его назначения или типа, как предложил Кгианнакакис, кажется общепринятым подходом.

Когда у нас есть DAO на основе веб-сервисов и DAO на основе ORM, мы используем и пакеты, и имена классов, чтобы отличать классы реализации от их интерфейсов и друг от друга. Я думаю, что размещение реализаций в разных пакетах сводится к тому, сколько классов у вас есть в пакете, насколько по-разному они реализованы и насколько вы хотите разделить вещи.

3
ответ дан 26 November 2019 в 23:35
поделиться

Вот что мы используем:

  • XxxDAO (доступ к данным Объект) - Отвечает за непосредственное взаимодействие с EntityManager, источником данных JDBC, файловой системой и т. Д. Должен содержать только логику сохранения, такую ​​как SQL или JPA-QL, но не (или как можно меньше) бизнес-логику. Доступно только для менеджеров.
  • XxxManager - Управляет объектами на бизнес-уровне, обычно выполняет операции CRUD, но добавляет необходимую бизнес-логику.
  • XxxService - Слой, на котором находится бизнес-логика. Должен "говорить" простыми объектами - строками, целыми числами и т. Д. - насколько это возможно.
  • XxxController - Уровень взаимодействия пользовательского интерфейса. Следует обращаться только к службам.
  • XxxUtilities / XxxUtils - Вспомогательные методы без сохранения состояния не должны зависеть от какой-либо службы в системе. Если вам нужна такая независимость, либо преобразуйте служебный класс в службу, либо добавьте результат службы в качестве параметра.

Для реализации мы добавляем суффикс Impl (XxxServiceImpl), чтобы отличить его от интерфейса, и если существует несколько реализаций или мы хотим добавить дополнительную информацию, мы добавляем его как префикс (JdbcXxxDaoImpl, GoogleMapsGeocodingServiceImpl и т. Д.). Имена классов в этом случае становятся немного длинными, но они очень информативны и самодокументируются.

56
ответ дан 26 November 2019 в 23:35
поделиться

В приведенном вами примере я бы использовал имена реализации, которые отражают то, как класс выполняет операции, например HibernateUserAccountManager, или JPAUserAccountManager, или JDBCUserAccountManager и т. Д., Или, возможно, просто UserAccountManagerDAO.

7
ответ дан 26 November 2019 в 23:35
поделиться

Вы также можете назвать интерфейс IUserAccountManager (это соглашение используется, например, в Eclipse RCP), а затем использовать UserAccountManager для реализации по умолчанию.

2
ответ дан 26 November 2019 в 23:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: