Что происходит, когда венгерская номенклатура встречается с JAVA?

Java задняя часть
Что происходит, когда венгерская номенклатура встречается с JAVA?

Это второй день моего участия в Gengwen Challenge, чтобы узнать подробности о мероприятии, пожалуйста, проверьте:Обновить вызов

Ставь лайк и потом смотри, вырабатывай полезную привычку

задний план

Когда я ранее рефакторил старый проект, поскольку базу данных нельзя было изменить, я все равно продолжал использовать старую базу данных. Для страховых компаний, даже если будет добавлено название интернет-страхования, бизнес и система по-прежнему остаются традиционными, и модель данных не будет легко обновляться; поэтому эта система относительно старая, и ее метод именования таблиц базы данных все ещеВенгерская номенклатура, от которого меня долго тошнило из-за такого способа именования при рефакторинге...

Венгерская номенклатура

Венгерская нотация, изобретенный Чарльзом Симеоне, программистом, работавшим в Xerox PARC с 1972 по 1981 год, за этим предшественникомстал главным дизайнером Microsoft.

Характерной чертой этой номенклатуры является добавлениепрефикс типа,нравится:

  • c_name- Имя, тип String (Char)
  • n_age- Возраст, число (число) типа
  • t_birthday- День рождения, дата/время (время) тип

Но не стоит недооценивать эту номенклатуру, тогда она была очень популярна, и некоторые системы до сих пор используют эту номенклатуру, например Microsoft Win32 API:image.pngБолее того, эта номенклатура не бесполезна и не имеет определенных преимуществ, по крайней мере, я могу с первого взгляда увидеть тип этого поля. ​

Просто сегодня это выглядит немного странно, да и не совсем вписывается в нынешний стиль дизайна, а было бы еще интереснее, если бы его поставили на имя человека:

  • мужчинаЧжао Си
  • ЖенскийСпасибо
  • мужчинаЛю Нэн

Когда венгерская номенклатура встречается с JAVA

Наша цель рефакторинга на этот раз — полностью переписать старую системную таблицу, не изменяя ее. Однако новая система разработана на языке Java, а в Java есть стандарт именования с верблюжьим регистром.Что произойдет, когда эта венгерская таблица нотаций будет перенесена в язык Java с верблюжьим регистром?

Например, после того, как имя c_name появится в Java, будет ли оно изменено на CName или cName? Это кажется немного странным, но в итоге мы выбрали CName и полностью сделали префикс типа заглавным, по крайней мере выглядит немного нормально, не так античеловечно

  • c_name -> CName
  • n_age -> NAge
  • t_birthday -> TBirthday

проблема сериализации

Я только определился со способом именования, и прежде чем долго радоваться, столкнулся с очень неудобной проблемой... ​

Поскольку это корзина семейства Spring, веб-уровень также использует Spring MVC. Библиотека обработки JSON по умолчанию для Spring MVC — Jackson.После того, как веб-уровень вернет JSON, данные будут выглядеть так:

{
    "nid":1,
    "ctitle":"Effective JAVA"
}

Но мой класс POJO переводит поля венгерской номенклатуры в верхний регистр, это выглядит так:

public class Book {
	private Integer NId;
	private String CTitle;

	public Integer getNId() {
		return NId;
	}

	public void setNId(Integer NId) {
		this.NId = NId;
	}

	public String getCTitle() {
		return CTitle;
	}

	public void setCTitle(String CTitle) {
		this.CTitle = CTitle;
	}
}

Имя поля в верхнем регистре становится строчным после конвертации в JSON. Если это поле в нижнем регистре отдано на фронтенд, то имя фронтенда обязательно будет строчным, и фронтенд тоже должен быть строчным, когда он отправляется на бэкенд. ​

Это потому, что мы сериализуем параметры в Джексоне и из него.Для Джексона мы можем входить и выходить, когда захотим, и мы все еще можем разобрать его.Это не кажется проблемой, но это немного отвратительно. ​

Но... не все так просто. Серверная часть не будет использовать все сообщения в качестве полей POJO, будут некоторые динамические поля, которые хранятся в карте. Для этих полей, хранящихся в Map, Джексон не будет преобразовывать в нижний регистр при выводе, но сохранит исходную форму в верхнем регистре, что приведет к полям внешнего интерфейса, хотя все они в венгерском стиле, но некоторые в верхнем регистре, а некоторые в нижнем... Хотя фронтенд не знаю бить людей или нет, но я не смею так играть

Различные библиотеки сериализации имеют разные механизмы обработки.

Обработка венгерской нотации Джексона

На самом деле, причина, по которой Джексон преобразуется в нижний регистр после сериализации, также хорошо объяснена.Спецификация дизайна Java заключается в том, что свойства в bean-компоненте украшаются приватными, а затем предоставляется геттер/сеттер для обеспечения чтения/записи. Затем во время сериализации Джексон получает доступ к значению свойства через метод получения поля и даже использует метод получения для разрешения имени свойства. ​

Стандарт именования методов получения в Java заключается в преобразовании нижнего регистра верблюда в верхний регистр верблюда Джексон анализирует getNID в nid при анализе имени поля через имя метода получения, поэтому окончательное выходное имя поля — nid нижнего регистра.

Обработка венгерской нотации FastJson

Изначально я хотел настроить процесс именования Джексона, но подумав об этом, я почувствовал, что в этом нет необходимости. Ведь наше именование не стандартное. Почему мы должны менять этот процесс именования? ​

Поэтому я попытался использовать другую библиотеку JSON, чтобы решить эту проблему с именами.Сначала попробуйте Ali FastJSON, чтобы увидеть, как справляется эта домашняя библиотека:

{
    "cTitle":"Effective JAVA",
    "nId":1
}

Когда я увидел этот результат сериализации, я чуть не сломал Backspace на своей клавиатуре... Имя свойства также анализируется методом геттера, и правила разбора двух библиотек могут быть разными... ​

В FastJson c в нижнем регистре, но T в заголовке по-прежнему в верхнем регистре, @#¥%...& 100 слов здесь опущены... ​

Успокоившись, я несколько раз про себя процитировала: «Я не виню других, это наша собственная проблема с именами. Не ваше дело, как люди это анализируют, если это не соответствует стандартам...» ​

Тем не менее, экология JAVA настолько хороша, и есть более двух библиотек JSON.Другое — это то, что Gson от Google тоже очень хорош!

Венгерская номенклатура Гсона

Поэтому я снова переключился на Gson, и после настройки Spring MVC Gson Converter результат был таким:

{
    "NId":1,
    "CTitle":"Effective JAVA"
}

Наконец, я переключился на библиотеку JSON, которая может нормально отображать исходное имя поля, но поскольку она может сохранять исходное имя поля вместо имени свойства, проанализированного в геттере, она не должна анализировать имя метода геттера. ​

Итак, я снова просмотрел исходный код Gson и обнаружил, что это прямойgetDeclaredFields(),ПотомmakeAccessible, и, наконец, непосредственно черезField.getValueспособ получить значение свойства напрямую. ​

По сравнению с методом получения списка свойств через геттер и последующим вызовом метода геттера для получения значения свойства в Джексоне и FastJson, практика форсирования доступа к приватным свойствам все еще слишком жестока, но мне это нравится, по крайней мере, это может легко решить мою проблему проблема

Другие проблемы с сериализацией

В дополнение к сериализации в форме JSON, некоторые двоичные сериализации также будут иметь эту неловкую проблему.Чтобы получить список свойств/значение свойства, нужно ли проанализировать метод получения или напрямую makeAccessible получить доступ к закрытым свойствам? ​

Я проверил это, например, в методе сериализации Dubbo по умолчанию (упрощенный Hession2 Dubbo), он все ещеgetDeclaredFields, а затем получить доступ к частной собственности ​

Во встроенной сериализации JDK ObjectOutputStream тожеgetDeclaredFields, а затем получить доступ к частной собственности. ​

Однако этот метод getDeclaredFields и последующего доступа к значениям приватных свойств также имеет некоторые недостатки. Например, при столкновении с путаницей в коде значения приватных свойств будут все зашифрованы, а общедоступные методы — нет, поэтому при встрече с запутанным кодом этот метод будет перепутан, и метод разбора через метод геттера будет будь без проблем. ​

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

Пополнить

благодарный@Пользователь 3323102545477Напоминаем, что Джексон очень мощный и поддерживает получение свойств конфигурации, которые можно настроитьVisibilityдобиться только путемFieldбез прохожденияgetterчтобы получить свойства:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,
        getterVisibility = JsonAutoDetect.Visibility.NONE)
public class Book {
    private Integer NId = 1;

    private String CName = "John";
}

Глобальная конфигурация более удобна:

ObjectMapper objectMapper = new ObjectMapper();

// 配置 field 为可见
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

// 配置 getter 不可见
objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);

Суммировать

Стандартный способ доступа к значениям приватных свойств в Java — через метод getter, но он по-прежнему предоставляет операцию makeAccessible, которая позволяет нам напрямую обращаться к приватным свойствам или приватным методам. ​

Я никогда не понимал, почему JDK был разработан таким образом, раз спецификация была указана, зачем открывать бэкдор? Если эту функцию ограничить, то все сериализованные библиотеки можно будет унифицировать, и не будет такой отвратительной проблемы несогласованности! ​

Но сравнивая три вышеупомянутые библиотеки сериализации, я думаю, что с ними все в порядке.Jackson/FastJson следуют стандартному пути и получают его честно через метод геттера, в то время как Gson немного агрессивен и напрямую обращается к приватным свойствам, каждый со своими преимуществами.

Дополнение: Джексон поддерживает способ получения атрибутов, по умолчанию черезgetterПолучить, но также можно настроить черезFieldПолучить, см. конфигурацию вышеПополнитьчасть

Нелегко быть оригинальным, и несанкционированная перепечатка запрещена. Если моя статья полезна для вас, пожалуйста, поставьте лайк/добавьте в избранное/подпишитесь, чтобы поддержать и поддержать ее ❤❤❤❤❤❤