SVN сохраняет нетронутые копии всех файлов Вами контроль проложенный под землей в .svn каталогах. Это называют текстовой основой. Это допускает быстрый diffs и возвращается. Во время различных операций SVN сделает контрольные суммы на этих основных текстом файлах для ловли проблем повреждения файла.
В целом, несоответствие контрольной суммы SVN означает файл, который не должен был быть изменен, был изменен так или иначе. Что это означает?
, Все они плохи.
ОДНАКО , я думаю, что Ваша проблема отличается. Посмотрите на сообщение об ошибке. Обратите внимание, что это ожидало некоторые хеши MD5, но вместо этого возвратило 'пустой указатель'. Если бы это было простой проблемой повреждения файла, то я ожидал бы, что у Вас было бы два различных хеша MD5 для ожидания/получения. То, что у Вас есть 'пустой указатель', подразумевает, что что-то еще неправильно.
у меня есть две теории:
В случае № 1, попытайтесь обновить до последней версии SVN. Возможно, также отправьте это в svn-devel списке рассылки ( http://svn.haxx.se ), таким образом, разработчики видят его.
В случае № 2, проверьте, чтобы видеть, заблокировали ли чему-нибудь файл. Можно загрузить копию Проводника Процесса для проверки. Обратите внимание, что Вы, вероятно, хотите видеть, у кого есть блокировка на текстовая основа файл, не фактический файл, который Вы пытались фиксировать.
Предположительно, вы боретесь с требованием постоянства case. Обычно это запах кода, но есть кое-что, что можно сделать. Возможно, вы захотите поднять и связать другой вопрос, в котором подробно описывается, почему вы пытаетесь переключиться.
Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());
String key = "something";
if (map.contains(key)) {
Object o = map.get(key);
}
В приведенном выше примере вы можете захотеть сопоставить «обработчики», что-то вроде
interface Handler {
public void doSomething();
}
, что затем превратит все это в поиск.
if (map.contains(key)) { map.get(key).doSomething(); }
Опять же, это немного запах, поэтому, пожалуйста, задайте вопрос, который иллюстрирует рассуждения.
re борется с требованием постоянства кейса. Обычно это запах кода, но кое-что можно сделать. Возможно, вы захотите поднять и связать другой вопрос, в котором подробно описывается, почему вы пытаетесь переключиться.Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());
String key = "something";
if (map.contains(key)) {
Object o = map.get(key);
}
В приведенном выше примере вы можете захотеть сопоставить «обработчики», что-то вроде
interface Handler {
public void doSomething();
}
, что затем превратит все это в поиск.
if (map.contains(key)) { map.get(key).doSomething(); }
Опять же, это немного запах, поэтому, пожалуйста, задайте вопрос, который иллюстрирует рассуждения.
re борется с требованием постоянства кейса. Обычно это запах кода, но кое-что можно сделать. Возможно, вы захотите поднять и связать другой вопрос, в котором подробно описывается, почему вы пытаетесь переключиться.Map<String,Object> map = new HasMap<String,Object>();
// ... insert stuff into map
// eg: map.add("something", new MyObject());
String key = "something";
if (map.contains(key)) {
Object o = map.get(key);
}
В приведенном выше примере вы можете захотеть сопоставить «обработчики», что-то вроде
interface Handler {
public void doSomething();
}
, что затем превратит все это в поиск.
if (map.contains(key)) { map.get(key).doSomething(); }
Опять же, это немного запах, поэтому, пожалуйста, задайте вопрос, который иллюстрирует рассуждения.
Реорганизация кода для использования полиморфизма может избавить от необходимости в инструкции switch. Однако есть несколько законных вариантов использования коммутатора, поэтому это зависит от вашей ситуации.
или можно представить себе что-то вроде динамического переключателя:
public interface Task<T>
{
public void doSomething(T context);
}
public Class SwitchCase<T>
{
Map<Integer,Task<T>> tasks;
Task<T> defaultTask;
public void choose(int choice, T context)
{
Task<T> t= this.tasks.get(choice);
if(t!=null) { t.doSomething(context); return;}
if(defaultTask!=null) { defaultTask.doSomething(context);}
}
}
Чем вы хотите заняться? Почему Switch-Case недостаточно хорош?
Быстрый ответ: используйте if-else
Думаю, в "Чистом коде" есть хорошая глава, посвященная переключению / регистру по сравнению с if / else.
Кроме того: я думаю, имеет смысл решить, можете ли вы уменьшить "шум" и сделайте код чище, используя регистр переключателя, полиморфизм или даже старый добрый if / else. Думаю, здесь большую роль играет количество дел.
if () {}
else if () {}
...
else if () {}
?
Но я бы не сказал, что это лучше ...
Как насчет оператора if
(вместе с else if
и else
)? В то время как переключатель
позволяет переключаться только с использованием равенства целочисленных или Enum типов, if
позволяет использовать любую логическую логику.
Вы всегда можете заменить переключатель на if-else if-else if-else if ...
, хотя я не понимаю, зачем вам это нужно. В зависимости от контекста переключатели
также иногда могут быть заменены массивами или хэш-картами.
Если в вашем коде много операторов switch / case и они сводят вас с ума.
Вы можете выбрать рефакторинг: Замените условное выражение полиморфизмом.
Допустим, у вас есть программное обеспечение, которое используется для сохранения информации на различных устройствах: определены 4 операции сохранения: выборка, сохранение, удаление, обновление , которые могут быть реализованы с помощью механизма сохранения N-числа (плоская файлы, сеть, СУБД, XML и т. д.).
Ваш код должен поддерживать их все, поэтому в 4 разных местах у вас есть это:
ДО
class YourProblematicClass {
....
public void fetchData( Object criteria ) {
switch ( this.persitanceType ) {
case FilePersistance:
// open file
// read it
// find the criteria
// build the data
// close it.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// retrieve the data
// build the data
// close connection
break();
case DataBasePersistace:
// Get a jdbc connection
// create the query
// execute the query
// fetch and build data
// close connection
break;
}
return data;
}
То же самое для сохранения / удаления / обновления
public void saveData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
// open file, go to EOF, write etc.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// etc
break();
case DataBasePersistace:
// Get a jdbc connection, query, execute...
break;
}
}
И так далее ....
public void deleteData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
public void updateData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
Использование переключателя / Оператор case становится проблематичным:
Каждый раз, когда вы хотите добавить новый тип, вы должны вставлять новый переключатель / регистр в каждый раздел.
Часто некоторые типы похожи, но они не Не нужен другой переключатель / регистр (вы могли бы их каскадировать)
Итак, рефакторинг здесь можно было бы добавить интерфейс или абстрактный тип, а различные типы реализуют этот интерфейс и делегировать ответственность этому объекту.
Таким образом, у вас будет что-то вроде этого:
ПОСЛЕ
public interface PersistenceManager {
public void fetchData( Object criteria );
public void saveData( Object toSave );
public void deleteData( Object toDelete );
public void updateData( Object toUpdate );
}
И разные реализации
public class FilePersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// open file
// read it
// find the criteria
// build the data
// close it.
}
public void saveData( Object toSave ) {
// open file, go to EOF etc.
}
public void deleteData( Object toDelete ){
....
}
public void updateData( Object toUpdate ){
....
}
}
И другие типы будут реализованы в соответствии с их логикой. Сеть будет иметь дело с сокетами и потоками, БД будет иметь дело с JDBC, ResultSets и т. Д. XML с узлом и т. Д.
public class NetworkPersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// Socket stuff
}
public void saveData( Object toSave ) {
// Socket stuff
}
public void deleteData( Object toDelete ){
// Socket stuff
}
public void updateData( Object toUpdate ){
// Socket stuff
}
}
public class DataBasePersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// JDBC stuff
}
public void saveData( Object toSave ) {
// JDBC stuff
}
public void deleteData( Object toDelete ){
// JDBC stuff
}
public void updateData( Object toUpdate ){
// JDBC stuff
}
}
И, наконец, вам просто нужно делегировать вызовы.
Позже:
public YouProblematicClass { // not longer that problematic
PersistamceManager persistance = // initialize with the right one.
public void fetchData( Object criteria ) {
// remove the switch and replace it with:
this.persistance.fetchData( criteria );
}
public void saveData( Object toSave ) {
// switch removed
this.persistance.saveData( toSave );
}
public void deleteData( Object toDelete ){
this.persistance.deleteData( toDelete );
}
public void updateData( Object toUpdate ){
this.persistance.updateData( toUpdate );
}
}
Итак, вы просто нужно создать правильный экземпляр для диспетчера сохраняемости в соответствии с типом только один раз. Затем все вызовы разрешаются полиморфизмом. Это одна из ключевых особенностей объектно-ориентированной технологии.
Если вы решите, что вам нужен другой менеджер сохраняемости, вы просто создаете новую реализацию и назначаете ее классу.
public WavePersistance implements PersistanceManager {
public void fetchData( Object criteria ) {
// ....
}
public void saveData( Object toSave ) {
// ....
}
public void deleteData( Object toDelete ){
// ....
}
public void updateData( Object toUpdate ){
// ....
}
}