Можете ли вы более конкретно рассказать о проблеме, с которой вы столкнулись при использовании объединений. Если вы хотите делать объединения, такие как sql, я думаю, что вы не можете сделать это, потому что это не реляционная база данных, как вы знаете. Но вы можете сделать аналогичные соединения, используя Aggregations или populate в мангусте. Более того, если вы хотите использовать компас для написания запросов, используйте панель запросов, вот ссылка , прикрепленная к тому, как написать запрос в панели запросов. Для выполнения агрегации с использованием компаса используйте вкладку агрегации в коллекции. Надеюсь, это поможет вам хотя бы решить некоторые ваши проблемы.
Возможная практика - использовать get префикс для методов, которые генерируют исключение, если результат не найден, и префикс find , если возможно значение null. Таким образом, на стороне клиента легко увидеть, может ли код иметь проблему с нулевым значением.
Конечно, следует избегать нулей, и Андрей Хельсберг сказал в интервью, что если бы C # был создан сейчас, у него были бы лучшие способы решения с возможностью нулевого значения. http://www.computerworld.com.au/article/261958/-z_programming_languages_c?pp=3&fp=&fpid=
NULL означает неизвестный / неопределенный.
Вы в основном нуждаетесь в этом при работе с базой данных, где данные просто «не определены (пока)». В вашем приложении NULL является хорошим возвращаемым типом для неисключительного поведения, но не по умолчанию.
Вы используете NULL, когда результат не является ожидаемым, но недостаточно серьезным для исключения.
У меня была похожая проблема, хотя я через исключение мне сказали, что я должен вернуть null,
Мы закончили читать
этот пост в блоге о досадных исключениях
Я бы рекомендовал прочитать.
Ответ на дизайн по контракту, который у вас есть, также будет моим решением:
if (myClass.SessionExists)
{
// Do something with myClass.Session
}
Одним из решений может быть объявление простого возвращаемого типа для таких вещей:
class Session
{
public bool Exists;
public string ID;
}
Session GetUserSession(int userID) {...}
...
Session session = GetUserSessionID(1);
if (session.Exists)
{
... use session.ID
}
Я вообще люблю избегать нулей, но строки - это особый случай. Я часто вызываю string.IsNullOrEmpty (). Настолько, что мы используем метод расширения для строки:
static class StringExtensions
{
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
}
Затем вы можете сделать:
string s = ... something
if (s.IsNullOrEmpty())
{
...
}
Кроме того, поскольку мы говорим о стиле кодирования:
Что с неестественно выглядящим "if (null = = ...) "стиль?" Это совершенно неуместно для C # - похоже, кто-то внес некоторый багаж C ++ в стили кодирования C #!
возврат null - это нормально, и следующее краткое и легкое для понимания:
var session = GetUserSessionID(1) ?? GetNewUserSession(1);
Сохраняйте простоту. Сделайте это максимально безболезненно для потребителя вашего типа. Это компромисс: время для реализации и полученные преимущества.
На мой взгляд, вы не должны исключать использование null как возвращаемое значение. Я думаю, что это справедливо во многих случаях. Но вы должны тщательно обдумывать плюсы и минусы каждого метода. Это полностью зависит от цели метода и ожиданий, которые могут иметь вызывающие.
Я лично часто использую возвращаемое значение null в тех случаях, когда вы можете ожидать, что метод не вернет неверный результат (т.е. поиск в базе данных первичным key, может возвращать только один экземпляр или none / null). Когда вы можете правильно ожидать, что метод вернет значение, вы должны использовать исключение.
В вашем конкретном примере, я думаю, это зависит от контекста системы. Если вызов, например, выполняется только из кода, в котором вы можете ожидать зарегистрированного пользователя, вы должны выбросить исключение. Однако если существует вероятность того, что ни один пользователь не вошел в систему, и поэтому у вас нет идентификатора сеанса для возврата, вы должны выбрать возврат null.
Нулевые значения намного лучше, чем магические значения, и имеют гораздо больший смысл.
Вы также можете попробовать написать метод TryGetUserSession.
bool TryGetUserSession (int sessionId, исходящий сеанс)
Также постарайтесь не писать nulls == ???, так как некоторым разработчикам труднее читать.
С уважением,
нули определенно лучше, т.е. более честны, чем "магические значения". Но они не должны возвращаться, когда произошла ошибка - для этого делаются исключения. Когда дело доходит до возврата коллекций ... я согласен с пустой коллекцией, чем с нулевой.
Почему бы вам не использовать вместо него шаблон проектирования Null ?
Я сам опасаюсь возвращать нули, хотя в вашем примере это, безусловно, кажется правильным.
Что важно, так это ясность о допустимости пустых значений как для аргументов, так и для возвращаемых значений. Этот должен быть указан как часть вашей документации API, если ваш язык не может выразить эту концепцию напрямую. (Java не может, я читал, что C # может.) Если входной параметр или возвращаемое значение может иметь значение null, обязательно сообщите пользователям, что это означает в контексте ваш API.
Наша самая большая база кода - это приложение Java, которое неуклонно растет за последнее десятилетие. Многие внутренние API очень неясны в отношении своего поведения WRT null. Это приводит к повсеместному росту числа нулевых проверок, потому что все программируют защищаясь.
Особенно уродливо: функции, возвращающие коллекции, возвращающие ноль вместо пустой коллекции. Какого черта !? Не делайте этого!
В случае со строками обязательно различите строки, которые должны быть там, но могут быть пустыми, и строки, которые действительно необязательны (могут быть нулевыми). При работе с XML мы часто сталкиваемся с этим различием: элементы, которые являются обязательными, но могут быть пустыми, по сравнению с элементами, которые являются необязательными.
Одна часть системы, которая обеспечивает запросы к XML-подобным структурам для реализации бизнес-правил, - это очень радикально относится к отсутствию нулей. Он везде использует шаблон «Нулевой объект». В этом контексте это оказывается полезным, потому что позволяет делать такие вещи, как:
A.children().first().matches("Blah")
Идея в том, что это выражение должно возвращать истину, если первый дочерний элемент A назван «Blah». Это победило t сбой, если у A нет дочерних элементов, потому что в этом случае first () возвращает NullNode, который реализует интерфейс узла, но никогда не «соответствует» чему-либо.
В итоге:
Мы всегда возвращаем пустые списки / коллекции и не возвращаем NULL списки / коллекции, потому что обработка пустых коллекций / списков снижает нагрузку на вызывающие функции.
Nullable - значения NULL особенно полезны, когда вы хотите избежать обработки «нулевых» значений из баз данных. Вы можете просто использовать GetDefaultOrValue для любого типа, допускающего значение NULL, не беспокоясь о том, что значение базы данных будет нулевым в ваших бизнес-объектах. Обычно мы определяем Nullables ТОЛЬКО в наших бизнес-объектах и там, где мы действительно хотим избежать проверки нулевых значений db и т. Д.
Я предпочитаю возвращать пустые коллекции вместо нулей, потому что это помогает избежать загромождения кода вызывающего абонента, например следующего:
if( list != null) {
foreach( Item item in list ) {
...
}
}